xref: /llvm-project/lldb/test/API/macosx/arm-corefile-regctx/create-arm-corefiles.cpp (revision 7777b305bff3ea156311612941664ef8280a4d10)
1 #include <mach-o/loader.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string>
5 #include <vector>
6 
7 
8 // Normally these are picked up by including <mach/thread_status.h>
9 // but that does a compile time check for the build host arch and
10 // only defines the ARM register context constants when building on
11 // an arm system.  We're creating fake corefiles, and might be
12 // creating them on an intel system.
13 #define ARM_THREAD_STATE 1
14 #define ARM_THREAD_STATE_COUNT 17
15 #define ARM_EXCEPTION_STATE 3
16 #define ARM_EXCEPTION_STATE_COUNT 3
17 #define ARM_THREAD_STATE64 6
18 #define ARM_THREAD_STATE64_COUNT 68
19 #define ARM_EXCEPTION_STATE64 7
20 #define ARM_EXCEPTION_STATE64_COUNT 4
21 
22 
23 union uint32_buf {
24   uint8_t bytebuf[4];
25   uint32_t val;
26 };
27 
28 union uint64_buf {
29   uint8_t bytebuf[8];
30   uint64_t val;
31 };
32 
add_uint64(std::vector<uint8_t> & buf,uint64_t val)33 void add_uint64(std::vector<uint8_t> &buf, uint64_t val) {
34   uint64_buf conv;
35   conv.val = val;
36   for (int i = 0; i < 8; i++)
37     buf.push_back(conv.bytebuf[i]);
38 }
39 
add_uint32(std::vector<uint8_t> & buf,uint32_t val)40 void add_uint32(std::vector<uint8_t> &buf, uint32_t val) {
41   uint32_buf conv;
42   conv.val = val;
43   for (int i = 0; i < 4; i++)
44     buf.push_back(conv.bytebuf[i]);
45 }
46 
armv7_lc_thread_load_command()47 std::vector<uint8_t> armv7_lc_thread_load_command() {
48   std::vector<uint8_t> data;
49   add_uint32(data, LC_THREAD);              // thread_command.cmd
50   add_uint32(data, 104);                    // thread_command.cmdsize
51   add_uint32(data, ARM_THREAD_STATE);       // thread_command.flavor
52   add_uint32(data, ARM_THREAD_STATE_COUNT); // thread_command.count
53   add_uint32(data, 0x00010000);             // r0
54   add_uint32(data, 0x00020000);             // r1
55   add_uint32(data, 0x00030000);             // r2
56   add_uint32(data, 0x00040000);             // r3
57   add_uint32(data, 0x00050000);             // r4
58   add_uint32(data, 0x00060000);             // r5
59   add_uint32(data, 0x00070000);             // r6
60   add_uint32(data, 0x00080000);             // r7
61   add_uint32(data, 0x00090000);             // r8
62   add_uint32(data, 0x000a0000);             // r9
63   add_uint32(data, 0x000b0000);             // r10
64   add_uint32(data, 0x000c0000);             // r11
65   add_uint32(data, 0x000d0000);             // r12
66   add_uint32(data, 0x000e0000);             // sp
67   add_uint32(data, 0x000f0000);             // lr
68   add_uint32(data, 0x00100000);             // pc
69   add_uint32(data, 0x00110000);             // cpsr
70 
71   add_uint32(data, ARM_EXCEPTION_STATE);       // thread_command.flavor
72   add_uint32(data, ARM_EXCEPTION_STATE_COUNT); // thread_command.count
73   add_uint32(data, 0x00003f5c);                // far
74   add_uint32(data, 0xf2000000);                // esr
75   add_uint32(data, 0x00000000);                // exception
76 
77   return data;
78 }
79 
arm64_lc_thread_load_command()80 std::vector<uint8_t> arm64_lc_thread_load_command() {
81   std::vector<uint8_t> data;
82   add_uint32(data, LC_THREAD);                // thread_command.cmd
83   add_uint32(data, 312);                      // thread_command.cmdsize
84   add_uint32(data, ARM_THREAD_STATE64);       // thread_command.flavor
85   add_uint32(data, ARM_THREAD_STATE64_COUNT); // thread_command.count
86   add_uint64(data, 0x0000000000000001);       // x0
87   add_uint64(data, 0x000000016fdff3c0);       // x1
88   add_uint64(data, 0x000000016fdff3d0);       // x2
89   add_uint64(data, 0x000000016fdff510);       // x3
90   add_uint64(data, 0x0000000000000000);       // x4
91   add_uint64(data, 0x0000000000000000);       // x5
92   add_uint64(data, 0x0000000000000000);       // x6
93   add_uint64(data, 0x0000000000000000);       // x7
94   add_uint64(data, 0x000000010000d910);       // x8
95   add_uint64(data, 0x0000000000000001);       // x9
96   add_uint64(data, 0xe1e88de000000000);       // x10
97   add_uint64(data, 0x0000000000000003);       // x11
98   add_uint64(data, 0x0000000000000148);       // x12
99   add_uint64(data, 0x0000000000004000);       // x13
100   add_uint64(data, 0x0000000000000008);       // x14
101   add_uint64(data, 0x0000000000000000);       // x15
102   add_uint64(data, 0x0000000000000000);       // x16
103   add_uint64(data, 0x0000000100003f5c);       // x17
104   add_uint64(data, 0x0000000000000000);       // x18
105   add_uint64(data, 0x0000000100003f5c);       // x19
106   add_uint64(data, 0x000000010000c000);       // x20
107   add_uint64(data, 0x000000010000d910);       // x21
108   add_uint64(data, 0x000000016fdff250);       // x22
109   add_uint64(data, 0x000000018ce12366);       // x23
110   add_uint64(data, 0x000000016fdff1d0);       // x24
111   add_uint64(data, 0x0000000000000001);       // x25
112   add_uint64(data, 0x0000000000000000);       // x26
113   add_uint64(data, 0x0000000000000000);       // x27
114   add_uint64(data, 0x0000000000000000);       // x28
115   add_uint64(data, 0x000000016fdff3a0);       // fp
116   add_uint64(data, 0x000000018cd97f28);       // lr
117   add_uint64(data, 0x000000016fdff140);       // sp
118   add_uint64(data, 0x0000000100003f5c);       // pc
119   add_uint32(data, 0x80001000);               // cpsr
120 
121   add_uint32(data, 0x00000000); // padding
122 
123   add_uint32(data, ARM_EXCEPTION_STATE64);       // thread_command.flavor
124   add_uint32(data, ARM_EXCEPTION_STATE64_COUNT); // thread_command.count
125   add_uint64(data, 0x0000000100003f5c);          // far
126   add_uint32(data, 0xf2000000);                  // esr
127   add_uint32(data, 0x00000000);                  // exception
128 
129   return data;
130 }
131 
132 enum arch { unspecified, armv7, arm64 };
133 
main(int argc,char ** argv)134 int main(int argc, char **argv) {
135   if (argc != 3) {
136     fprintf(stderr,
137             "usage: create-arm-corefiles [armv7|arm64] <output-core-name>\n");
138     exit(1);
139   }
140 
141   arch arch = unspecified;
142 
143   if (strcmp(argv[1], "armv7") == 0)
144     arch = armv7;
145   else if (strcmp(argv[1], "arm64") == 0)
146     arch = arm64;
147   else {
148     fprintf(stderr, "unrecognized architecture %s\n", argv[1]);
149     exit(1);
150   }
151 
152   // An array of load commands (in the form of byte arrays)
153   std::vector<std::vector<uint8_t>> load_commands;
154 
155   // An array of corefile contents (page data, lc_note data, etc)
156   std::vector<uint8_t> payload;
157 
158   // First add all the load commands / payload so we can figure out how large
159   // the load commands will actually be.
160   if (arch == armv7)
161     load_commands.push_back(armv7_lc_thread_load_command());
162   else if (arch == arm64)
163     load_commands.push_back(arm64_lc_thread_load_command());
164 
165   int size_of_load_commands = 0;
166   for (const auto &lc : load_commands)
167     size_of_load_commands += lc.size();
168 
169   int header_and_load_cmd_room =
170       sizeof(struct mach_header_64) + size_of_load_commands;
171 
172   // Erase the load commands / payload now that we know how much space is
173   // needed, redo it.
174   load_commands.clear();
175   payload.clear();
176 
177   if (arch == armv7)
178     load_commands.push_back(armv7_lc_thread_load_command());
179   else if (arch == arm64)
180     load_commands.push_back(arm64_lc_thread_load_command());
181 
182   struct mach_header_64 mh;
183   mh.magic = MH_MAGIC_64;
184   if (arch == armv7) {
185     mh.cputype = CPU_TYPE_ARM;
186     mh.cpusubtype = CPU_SUBTYPE_ARM_V7M;
187   } else if (arch == arm64) {
188     mh.cputype = CPU_TYPE_ARM64;
189     mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL;
190   }
191   mh.filetype = MH_CORE;
192   mh.ncmds = load_commands.size();
193   mh.sizeofcmds = size_of_load_commands;
194   mh.flags = 0;
195   mh.reserved = 0;
196 
197   FILE *f = fopen(argv[2], "w");
198 
199   if (f == nullptr) {
200     fprintf(stderr, "Unable to open file %s for writing\n", argv[2]);
201     exit(1);
202   }
203 
204   fwrite(&mh, sizeof(struct mach_header_64), 1, f);
205 
206   for (const auto &lc : load_commands)
207     fwrite(lc.data(), lc.size(), 1, f);
208 
209   fseek(f, header_and_load_cmd_room, SEEK_SET);
210 
211   fwrite(payload.data(), payload.size(), 1, f);
212 
213   fclose(f);
214 }
215