Skip to content

Commit 8461c00

Browse files
authored
[lldb] Pass address expression command args through FixAnyAddress (llvm#147011)
Commands that take an address expression/address through the OptionArgParser::ToAddress method, which has filtered this user-specified address through one of the Process Fix methods to clear non-addressable bits (MTE, PAC, top byte ignore, etc). We don't know what class of address this is, IMEM or DMEM, but this method is passing the addresses through Process::FixCodeAddress, and on at least one target, FixCodeAddress clears low bits which are invalid for instructions. Correct this to use FixAnyAddress, which doesn't make alignment assumptions. The actual issue found was by people debugging on a 32-bit ARM Cortex-M part, who tried to do a memory read from an odd address, and lldb returned results starting at the next lower even address. rdar://154885727
1 parent d906079 commit 8461c00

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

lldb/source/Interpreter/OptionArgParser.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,7 @@ lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx,
175175
lldb::addr_t addr = *maybe_addr;
176176

177177
if (Process *process = exe_ctx->GetProcessPtr())
178-
if (ABISP abi_sp = process->GetABI())
179-
addr = abi_sp->FixCodeAddress(addr);
178+
addr = process->FixAnyAddress(addr);
180179

181180
return addr;
182181
}

lldb/test/API/macosx/arm-corefile-regctx/TestArmMachoCorefileRegctx.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Test that Mach-O armv7/arm64 corefile register contexts are read by lldb."""
22

3-
43
import os
54
import re
65
import subprocess
@@ -44,6 +43,11 @@ def test_armv7_corefile(self):
4443
self.assertTrue(exception.IsValid())
4544
self.assertEqual(exception.GetValueAsUnsigned(), 0x00003F5C)
4645

46+
# read 4 bytes starting at $sp-1 (an odd/unaligned address on this arch),
47+
# formatted hex.
48+
# aka `mem read -f x -s 1 -c 4 $sp-1`
49+
self.expect("x/4bx $sp-1", substrs=["0x000dffff", "0x1f 0x20 0x21 0x22"])
50+
4751
def test_arm64_corefile(self):
4852
### Create corefile
4953
retcode = call(self.create_corefile + " arm64 " + self.corefile, shell=True)

lldb/test/API/macosx/arm-corefile-regctx/create-arm-corefiles.cpp

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,30 @@
1010
// only defines the ARM register context constants when building on
1111
// an arm system. We're creating fake corefiles, and might be
1212
// creating them on an intel system.
13+
#ifndef ARM_THREAD_STATE
1314
#define ARM_THREAD_STATE 1
15+
#endif
16+
#ifndef ARM_THREAD_STATE_COUNT
1417
#define ARM_THREAD_STATE_COUNT 17
18+
#endif
19+
#ifndef ARM_EXCEPTION_STATE
1520
#define ARM_EXCEPTION_STATE 3
21+
#endif
22+
#ifndef ARM_EXCEPTION_STATE_COUNT
1623
#define ARM_EXCEPTION_STATE_COUNT 3
24+
#endif
25+
#ifndef ARM_THREAD_STATE64
1726
#define ARM_THREAD_STATE64 6
27+
#endif
28+
#ifndef ARM_THREAD_STATE64_COUNT
1829
#define ARM_THREAD_STATE64_COUNT 68
30+
#endif
31+
#ifndef ARM_EXCEPTION_STATE64
1932
#define ARM_EXCEPTION_STATE64 7
33+
#endif
34+
#ifndef ARM_EXCEPTION_STATE64_COUNT
2035
#define ARM_EXCEPTION_STATE64_COUNT 4
21-
36+
#endif
2237

2338
union uint32_buf {
2439
uint8_t bytebuf[4];
@@ -129,6 +144,27 @@ std::vector<uint8_t> arm64_lc_thread_load_command() {
129144
return data;
130145
}
131146

147+
std::vector<uint8_t> lc_segment(uint32_t fileoff,
148+
uint32_t lc_segment_data_size) {
149+
std::vector<uint8_t> data;
150+
// 0x000e0000 is the value of $sp in the armv7 LC_THREAD
151+
uint32_t start_vmaddr = 0x000e0000 - (lc_segment_data_size / 2);
152+
add_uint32(data, LC_SEGMENT); // segment_command.cmd
153+
add_uint32(data, sizeof(struct segment_command)); // segment_command.cmdsize
154+
for (int i = 0; i < 16; i++)
155+
data.push_back(0); // segment_command.segname[16]
156+
add_uint32(data, start_vmaddr); // segment_command.vmaddr
157+
add_uint32(data, lc_segment_data_size); // segment_command.vmsize
158+
add_uint32(data, fileoff); // segment_command.fileoff
159+
add_uint32(data, lc_segment_data_size); // segment_command.filesize
160+
add_uint32(data, 3); // segment_command.maxprot
161+
add_uint32(data, 3); // segment_command.initprot
162+
add_uint32(data, 0); // segment_command.nsects
163+
add_uint32(data, 0); // segment_command.flags
164+
165+
return data;
166+
}
167+
132168
enum arch { unspecified, armv7, arm64 };
133169

134170
int main(int argc, char **argv) {
@@ -157,10 +193,12 @@ int main(int argc, char **argv) {
157193

158194
// First add all the load commands / payload so we can figure out how large
159195
// the load commands will actually be.
160-
if (arch == armv7)
196+
if (arch == armv7) {
161197
load_commands.push_back(armv7_lc_thread_load_command());
162-
else if (arch == arm64)
198+
load_commands.push_back(lc_segment(0, 0));
199+
} else if (arch == arm64) {
163200
load_commands.push_back(arm64_lc_thread_load_command());
201+
}
164202

165203
int size_of_load_commands = 0;
166204
for (const auto &lc : load_commands)
@@ -174,19 +212,33 @@ int main(int argc, char **argv) {
174212
load_commands.clear();
175213
payload.clear();
176214

177-
if (arch == armv7)
215+
int payload_fileoff = (header_and_load_cmd_room + 4096 - 1) & ~(4096 - 1);
216+
217+
const int lc_segment_data_size = 64;
218+
if (arch == armv7) {
178219
load_commands.push_back(armv7_lc_thread_load_command());
179-
else if (arch == arm64)
220+
load_commands.push_back(lc_segment(payload_fileoff, lc_segment_data_size));
221+
} else if (arch == arm64) {
180222
load_commands.push_back(arm64_lc_thread_load_command());
223+
}
224+
225+
if (arch == armv7)
226+
for (int i = 0; i < lc_segment_data_size;
227+
i++) // from segment_command.filesize
228+
payload.push_back(i);
181229

182230
struct mach_header_64 mh;
183-
mh.magic = MH_MAGIC_64;
231+
int header_size;
184232
if (arch == armv7) {
233+
mh.magic = MH_MAGIC;
185234
mh.cputype = CPU_TYPE_ARM;
186235
mh.cpusubtype = CPU_SUBTYPE_ARM_V7M;
236+
header_size = sizeof(struct mach_header);
187237
} else if (arch == arm64) {
238+
mh.magic = MH_MAGIC_64;
188239
mh.cputype = CPU_TYPE_ARM64;
189240
mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL;
241+
header_size = sizeof(struct mach_header_64);
190242
}
191243
mh.filetype = MH_CORE;
192244
mh.ncmds = load_commands.size();
@@ -201,12 +253,12 @@ int main(int argc, char **argv) {
201253
exit(1);
202254
}
203255

204-
fwrite(&mh, sizeof(struct mach_header_64), 1, f);
256+
fwrite(&mh, header_size, 1, f);
205257

206258
for (const auto &lc : load_commands)
207259
fwrite(lc.data(), lc.size(), 1, f);
208260

209-
fseek(f, header_and_load_cmd_room, SEEK_SET);
261+
fseek(f, payload_fileoff, SEEK_SET);
210262

211263
fwrite(payload.data(), payload.size(), 1, f);
212264

0 commit comments

Comments
 (0)