Skip to content

Commit 04d72df

Browse files
authored
src: Add support for big endian systems (#120)
Read values correctly converting for endianess as required. Generally this just means using LLDB's ReadUnsignedFromMemory function but there are a few places where we optimise reading values or where we only want one byte from a larger field where we need to account for endianess ourselves. PR-URL: #120 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Fedor Indutny <fedor@indutny.com>
1 parent 1c944fe commit 04d72df

6 files changed

Lines changed: 47 additions & 14 deletions

File tree

src/llnode.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ bool PrintCmd::DoExecute(SBDebugger d, char** cmd,
200200
v8::Error err;
201201
std::string res = v8_value.Inspect(&inspect_options, err);
202202
if (err.Fail()) {
203-
result.SetError("Failed to evaluate expression");
203+
result.SetError(err.GetMessage());
204204
return false;
205205
}
206206

src/llscan.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace llnode {
1919

20+
using lldb::ByteOrder;
2021
using lldb::SBCommandReturnObject;
2122
using lldb::SBDebugger;
2223
using lldb::SBError;
@@ -1204,11 +1205,19 @@ bool LLScan::ScanHeapForObjects(lldb::SBTarget target,
12041205
return true;
12051206
}
12061207

1208+
inline static ByteOrder GetHostByteOrder() {
1209+
union {
1210+
uint8_t a[2];
1211+
uint16_t b;
1212+
} u = {{0, 1}};
1213+
return u.b == 1 ? ByteOrder::eByteOrderBig : ByteOrder::eByteOrderLittle;
1214+
}
12071215

12081216
void LLScan::ScanMemoryRanges(FindJSObjectsVisitor& v) {
12091217
bool done = false;
12101218

12111219
const uint64_t addr_size = process_.GetAddressByteSize();
1220+
bool swap_bytes = process_.GetByteOrder() != GetHostByteOrder();
12121221

12131222
// Pages are usually around 1mb, so this should more than enough
12141223
const uint64_t block_size = 1024 * 1024 * addr_size;
@@ -1258,12 +1267,19 @@ void LLScan::ScanMemoryRanges(FindJSObjectsVisitor& v) {
12581267
for (size_t j = 0; j + addr_size <= loaded;) {
12591268
uint64_t value;
12601269

1261-
if (addr_size == 4)
1270+
if (addr_size == 4) {
12621271
value = *reinterpret_cast<uint32_t*>(&block[j]);
1263-
else if (addr_size == 8)
1272+
if (swap_bytes) {
1273+
value = __builtin_bswap32(value);
1274+
}
1275+
} else if (addr_size == 8) {
12641276
value = *reinterpret_cast<uint64_t*>(&block[j]);
1265-
else
1277+
if (swap_bytes) {
1278+
value = __builtin_bswap64(value);
1279+
}
1280+
} else {
12661281
break;
1282+
}
12671283

12681284
increment = v.Visit(j + searchAddress, value);
12691285
if (increment == 0) break;

src/llv8-constants.cc

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,15 @@ static int64_t LookupConstant(SBTarget target, const char* name, int64_t def,
6868

6969
// NOTE: size could be bigger for at the end symbols
7070
if (size >= 8) {
71-
process.ReadMemory(addr, &res, 8, sberr);
71+
res = process.ReadUnsignedFromMemory(addr, 8, sberr);
7272
} else if (size == 4) {
73-
int32_t tmp;
74-
process.ReadMemory(addr, &tmp, size, sberr);
73+
int32_t tmp = process.ReadUnsignedFromMemory(addr, size, sberr);
7574
res = static_cast<int64_t>(tmp);
7675
} else if (size == 2) {
77-
int16_t tmp;
78-
process.ReadMemory(addr, &tmp, size, sberr);
76+
int16_t tmp = process.ReadUnsignedFromMemory(addr, size, sberr);
7977
res = static_cast<int64_t>(tmp);
8078
} else if (size == 1) {
81-
int8_t tmp;
82-
process.ReadMemory(addr, &tmp, size, sberr);
79+
int8_t tmp = process.ReadUnsignedFromMemory(addr, size, sberr);
8380
res = static_cast<int64_t>(tmp);
8481
} else {
8582
err = Error::Failure("Unexpected symbol size");

src/llv8-inl.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ inline int64_t HeapObject::GetType(Error& err) {
8181

8282

8383
inline int64_t Map::GetType(Error& err) {
84-
int64_t type = LoadField(v8()->map()->kInstanceAttrsOffset, err);
84+
int64_t type =
85+
v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceAttrsOffset), 2, err);
8586
if (err.Fail()) return -1;
87+
8688
return type & 0xff;
8789
}
8890

@@ -150,15 +152,16 @@ ACCESSOR(Map, InstanceDescriptors, map()->kInstanceDescriptorsOffset,
150152
HeapObject)
151153

152154
inline int64_t Map::BitField3(Error& err) {
153-
return LoadField(v8()->map()->kBitField3Offset, err) & 0xffffffff;
155+
return v8()->LoadUnsigned(LeaField(v8()->map()->kBitField3Offset), 4, err);
154156
}
155157

156158
inline int64_t Map::InObjectProperties(Error& err) {
157159
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
158160
}
159161

160162
inline int64_t Map::InstanceSize(Error& err) {
161-
return (LoadField(v8()->map()->kInstanceSizeOffset, err) & 0xff) *
163+
return v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceSizeOffset), 1,
164+
err) *
162165
v8()->common()->kPointerSize;
163166
}
164167

src/llv8.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ int64_t LLV8::LoadPtr(int64_t addr, Error& err) {
7373
}
7474

7575

76+
int64_t LLV8::LoadUnsigned(int64_t addr, uint32_t byte_size, Error& err) {
77+
SBError sberr;
78+
int64_t value = process_.ReadUnsignedFromMemory(static_cast<addr_t>(addr),
79+
byte_size, sberr);
80+
81+
if (sberr.Fail()) {
82+
// TODO(indutny): add more information
83+
err = Error::Failure("Failed to load V8 value");
84+
return -1;
85+
}
86+
87+
err = Error::Ok();
88+
return value;
89+
}
90+
91+
7692
double LLV8::LoadDouble(int64_t addr, Error& err) {
7793
SBError sberr;
7894
int64_t value = process_.ReadUnsignedFromMemory(static_cast<addr_t>(addr),

src/llv8.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ class LLV8 {
462462

463463
int64_t LoadConstant(const char* name);
464464
int64_t LoadPtr(int64_t addr, Error& err);
465+
int64_t LoadUnsigned(int64_t addr, uint32_t byte_size, Error& err);
465466
double LoadDouble(int64_t addr, Error& err);
466467
std::string LoadBytes(int64_t length, int64_t addr, Error& err);
467468
std::string LoadString(int64_t addr, int64_t length, Error& err);

0 commit comments

Comments
 (0)