diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/decompiler-ls.h | 8 | ||||
-rw-r--r-- | src/decompiler.cc | 36 |
2 files changed, 38 insertions, 6 deletions
diff --git a/src/decompiler-ls.h b/src/decompiler-ls.h index 80ec2654..3f59d6ce 100644 --- a/src/decompiler-ls.h +++ b/src/decompiler-ls.h @@ -78,7 +78,7 @@ struct LoadStoreTracking { }; struct LSVar { - std::map<uint32_t, LSAccess> accesses; + std::map<uint64_t, LSAccess> accesses; bool struct_layout = true; Type same_type = Type::Any; Address same_align = kInvalidAddress; @@ -119,7 +119,7 @@ struct LoadStoreTracking { } } - void LoadStore(uint32_t offset, Opcode opc, Type type, Address align, + void LoadStore(uint64_t offset, Opcode opc, Type type, Address align, const Node& addr_exp) { auto byte_size = opc.GetMemorySize(); type = GetMemoryType(type, opc); @@ -178,7 +178,7 @@ struct LoadStoreTracking { var.second.struct_layout = false; continue; } - uint32_t cur_offset = 0; + uint64_t cur_offset = 0; uint32_t idx = 0; for (auto& access : var.second.accesses) { access.second.idx = idx++; @@ -234,7 +234,7 @@ struct LoadStoreTracking { return ""; } - std::string GenAccess(uint32_t offset, const Node& addr_exp) const { + std::string GenAccess(uint64_t offset, const Node& addr_exp) const { auto name = AddrExpName(addr_exp); if (name.empty()) { return ""; diff --git a/src/decompiler.cc b/src/decompiler.cc index db71bf42..a0f710c4 100644 --- a/src/decompiler.cc +++ b/src/decompiler.cc @@ -224,7 +224,16 @@ struct Decompiler { return cat(name, ":", struc.empty() ? GetDecompTypeName(t) : struc); } - void LoadStore(Value &val, const Node& addr_exp, uint32_t offset, + bool ConstIntVal(const Expr* e, uint64_t &dest) { + dest = 0; + if (!e || e->type() != ExprType::Const) return false; + auto& c = cast<ConstExpr>(e)->const_; + if (c.type != Type::I32 && c.type != Type::I64) return false; + dest = c.type == Type::I32 ? c.u32 : c.u64; + return true; + } + + void LoadStore(Value &val, const Node& addr_exp, uint64_t offset, Opcode opc, Address align, Type op_type) { bool append_type = true; auto access = lst.GenAccess(offset, addr_exp); @@ -240,6 +249,30 @@ struct Decompiler { return; } } + // Detect absolute addressing, which we try to turn into references to the + // data section when possible. + uint64_t abs_base; + if (ConstIntVal(addr_exp.e, abs_base)) { + // We don't care what part of the absolute address was stored where, + // 1[0] and 0[1] are the same. + abs_base += offset; + // FIXME: make this less expensive with a binary search or whatever. + for (auto dat : mc.module.data_segments) { + uint64_t dat_base; + if (dat->offset.size() == 1 && + ConstIntVal(&dat->offset.front(), dat_base) && + abs_base >= dat_base && + abs_base < dat_base + dat->data.size()) { + // We are inside the range of this data segment! + // Turn expression into data_name[index] + val = Value { { dat->name }, Precedence::Atomic }; + // The new offset is from the start of the data segment, instead of + // whatever it was.. this may be a different value from both the + // original const and offset! + offset = abs_base - dat_base; + } + } + } // Do the load/store as a generalized indexing operation. // The offset is divisible by the alignment in 99.99% of // cases, but the spec doesn't guarantee it, so we must @@ -697,7 +730,6 @@ struct Decompiler { // Data. for (auto dat : mc.module.data_segments) { - s += cat("data ", dat->name, "(offset: ", InitExp(dat->offset), ") = "); auto ds = BinaryToString(dat->data); if (ds.size() > target_exp_width / 2) { |