summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/decompiler-ls.h8
-rw-r--r--src/decompiler.cc36
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) {