9 typedef unsigned long elf64_ptr_t;
10 typedef unsigned short elf64_hlf_t;
11 typedef unsigned long elf64_off_t;
12 typedef int elf64_swd_t;
13 typedef unsigned int elf64_wrd_t;
14 typedef unsigned long elf64_xwrd_t;
15 typedef long elf64_sxwrd_t;
17 typedef unsigned int elf32_ptr_t;
18 typedef unsigned short elf32_hlf_t;
19 typedef unsigned int elf32_off_t;
20 typedef unsigned int elf32_swd_t;
21 typedef unsigned int elf32_wrd_t;
28 typedef unsigned long ptr_t;
30 struct elf_generic_ehdr
34 unsigned int signature;
36 } __attribute__((packed));
37 unsigned char e_ident[16];
39 unsigned short e_type;
40 unsigned short e_machine;
41 unsigned int e_version;
46 struct elf_generic_ehdr head;
52 elf32_hlf_t e_phentsize;
54 elf32_hlf_t e_shentsize;
56 elf32_hlf_t e_shstrndx;
61 struct elf_generic_ehdr head;
67 elf64_hlf_t e_phentsize;
69 elf64_hlf_t e_shentsize;
71 elf64_hlf_t e_shstrndx;
81 elf64_xwrd_t p_filesz;
108 struct elf_section* secs;
113 #define MAPPED_SIZE (256 << 10)
115 static struct elf_generic_ehdr*
116 __load_elf(const char* path)
119 struct elf_generic_ehdr* ehdr;
121 fd = open(path, O_RDONLY);
123 printf("fail to open elf: %s\n", strerror(errno));
127 ehdr = mmap(NULL, MAPPED_SIZE, PROT_READ, MAP_SHARED, fd, 0);
128 if ((void*)ehdr == (void*)-1) {
129 printf("fail to mmap elf (%d): %s\n", errno, strerror(errno));
137 __wr_mapentry(struct ksec_genctx* ctx, struct elf_section* sec)
139 printf("/* --- entry --- */\n");
140 printf("%s 0x%lx\n", ctx->prefix, sec->va);
141 printf("%s 0x%lx\n", ctx->prefix, sec->pa);
142 printf(".4byte 0x%x\n", sec->memsz);
143 printf(".4byte 0x%x\n", sec->flags);
147 __wr_maplast(struct ksec_genctx* ctx, struct elf_section* sec)
149 printf("/* --- entry --- */\n");
150 printf("%s 0x%lx\n", ctx->prefix, sec->va);
151 printf("%s 0x%lx\n", ctx->prefix, sec->pa);
152 printf(".4byte (__kexec_end - 0x%lx)\n", sec->va);
153 printf(".4byte 0x%x\n", sec->flags);
156 #define SIZEPF32 ".4byte"
157 #define SIZEPF64 ".8byte"
158 #define gen_ksec_map(bits, ctx, ehdr) \
160 struct elf##bits##_ehdr *_e; \
161 struct elf##bits##_phdr *phdr, *phent; \
162 _e = (struct elf##bits##_ehdr*)(ehdr); \
163 phdr = (struct elf##bits##_phdr*)((ptr_t)_e + _e->e_phoff); \
164 for (int i = 0, j = 0; i < _e->e_phnum; i++) { \
166 if (phent->p_type != PT_LOAD) { \
169 ctx.secs[j++] = (struct elf_section) { \
172 .memsz = phent->p_memsz, \
173 .flags = phent->p_flags, \
178 #define count_loadable(bits, ehdr) \
180 struct elf##bits##_ehdr *_e; \
181 struct elf##bits##_phdr *phdr, *phent; \
182 int all_loadable = 0; \
183 _e = (struct elf##bits##_ehdr*)(ehdr); \
184 phdr = (struct elf##bits##_phdr*)((ptr_t)_e + _e->e_phoff); \
185 for (int i = 0; i < _e->e_phnum; i++) { \
187 if (phent->p_type == PT_LOAD) { \
195 __emit_size(struct ksec_genctx* genctx)
198 unsigned int size = 0;
199 int n = genctx->size - 1;
202 first two LOAD are boot text and data.
203 we are calculating the kernel size, so
206 for (int i = 2; i < n; i++)
208 size += genctx->secs[i].memsz;
211 va = genctx->secs[n].va;
212 printf(".4byte 0x%x + (__kexec_end - 0x%lx)\n", size, va);
216 __generate_kernelmap(struct elf_generic_ehdr* ehdr)
219 printf(".section .autogen.ksecmap, \"a\", @progbits\n"
220 ".global __autogen_ksecmap\n"
221 "__autogen_ksecmap:\n");
223 struct ksec_genctx genctx;
225 if (ehdr->class == ELFCLASS32) {
226 genctx.size = count_loadable(32, ehdr);
227 genctx.prefix = SIZEPF32;
229 genctx.size = count_loadable(64, ehdr);
230 genctx.prefix = SIZEPF64;
233 genctx.secs = calloc(genctx.size, sizeof(struct elf_section));
235 if (ehdr->class == ELFCLASS32) {
236 gen_ksec_map(32, genctx, ehdr);
239 genctx.size = count_loadable(64, ehdr);
240 gen_ksec_map(64, genctx, ehdr);
244 struct elf_section* sec_ent;
246 printf(".4byte 0x%x\n", genctx.size);
247 __emit_size(&genctx);
250 Lunaix define the last LOAD phdr is variable
251 sized. that is the actual size will not be known
252 until after relink, so we need to emit a special
253 entry and let linker determine the size.
257 for (; i < genctx.size - 1; i++)
259 sec_ent = &genctx.secs[i];
260 __wr_mapentry(&genctx, sec_ent);
263 __wr_maplast(&genctx, &genctx.secs[i]);
266 #define MODE_GETARCH 1
267 #define MODE_GENLOAD 2
271 main(int argc, char* const* argv)
279 while ((c = getopt(argc, argv, "i:tph")) != -1)
296 printf("usage: elftool -i elf_file -pt [-o out]\n");
297 printf(" -t: get elf type.\n");
298 printf(" -p: generate load sections.\n");
303 printf("unknown option: '%c'", optopt);
310 printf("must specify an elf.\n");
314 struct elf_generic_ehdr* ehdr;
315 ehdr = __load_elf(path);
321 if (ehdr->signature != 0x464c457fU) {
322 printf("not an elf file\n");
326 if (mode == MODE_GETARCH) {
327 if (ehdr->class == ELFCLASS32) {
336 if (mode == MODE_GENLOAD) {
337 __generate_kernelmap(ehdr);