Lines Matching full:elf

21 #include <elf.h>
73 #define ELFDBG(elf, ...) \ argument
74 _elf_dbg(elf, __FILE__, __LINE__, __func__, __VA_ARGS__);
76 static inline void _elf_dbg(const struct kmod_elf *elf, const char *fname, unsigned line, const cha… in _elf_dbg() argument
81 (elf->class & KMOD_ELF_32) ? 32 : 64, in _elf_dbg()
82 (elf->class & KMOD_ELF_MSB) ? 'M' : 'L', in _elf_dbg()
89 #define ELFDBG(elf, ...) argument
130 static inline uint64_t elf_get_uint(const struct kmod_elf *elf, uint64_t offset, uint16_t size) in elf_get_uint() argument
137 assert(offset + size <= elf->size); in elf_get_uint()
138 if (offset + size > elf->size) { in elf_get_uint()
139 ELFDBG(elf, "out of bounds: %"PRIu64" + %"PRIu16" = %"PRIu64"> %"PRIu64" (ELF size)\n", in elf_get_uint()
140 offset, size, offset + size, elf->size); in elf_get_uint()
144 p = elf->memory + offset; in elf_get_uint()
145 if (elf->class & KMOD_ELF_MSB) { in elf_get_uint()
153 ELFDBG(elf, "size=%"PRIu16" offset=%"PRIu64" value=%"PRIu64"\n", in elf_get_uint()
159 static inline int elf_set_uint(struct kmod_elf *elf, uint64_t offset, uint64_t size, uint64_t value) in elf_set_uint() argument
164 ELFDBG(elf, "size=%"PRIu16" offset=%"PRIu64" value=%"PRIu64" write memory=%p\n", in elf_set_uint()
165 size, offset, value, elf->changed); in elf_set_uint()
168 assert(offset + size <= elf->size); in elf_set_uint()
169 if (offset + size > elf->size) { in elf_set_uint()
170 ELFDBG(elf, "out of bounds: %"PRIu64" + %"PRIu16" = %"PRIu64"> %"PRIu64" (ELF size)\n", in elf_set_uint()
171 offset, size, offset + size, elf->size); in elf_set_uint()
175 if (elf->changed == NULL) { in elf_set_uint()
176 elf->changed = malloc(elf->size); in elf_set_uint()
177 if (elf->changed == NULL) in elf_set_uint()
179 memcpy(elf->changed, elf->memory, elf->size); in elf_set_uint()
180 elf->memory = elf->changed; in elf_set_uint()
181 ELFDBG(elf, "copied memory to allow writing.\n"); in elf_set_uint()
184 p = elf->changed + offset; in elf_set_uint()
185 if (elf->class & KMOD_ELF_MSB) { in elf_set_uint()
200 static inline const void *elf_get_mem(const struct kmod_elf *elf, uint64_t offset) in elf_get_mem() argument
202 assert(offset < elf->size); in elf_get_mem()
203 if (offset >= elf->size) { in elf_get_mem()
204 ELFDBG(elf, "out-of-bounds: %"PRIu64" >= %"PRIu64" (ELF size)\n", in elf_get_mem()
205 offset, elf->size); in elf_get_mem()
208 return elf->memory + offset; in elf_get_mem()
211 static inline const void *elf_get_section_header(const struct kmod_elf *elf, uint16_t idx) in elf_get_section_header() argument
214 assert(idx < elf->header.section.count); in elf_get_section_header()
215 if (idx == SHN_UNDEF || idx >= elf->header.section.count) { in elf_get_section_header()
216 ELFDBG(elf, "invalid section number: %"PRIu16", last=%"PRIu16"\n", in elf_get_section_header()
217 idx, elf->header.section.count); in elf_get_section_header()
220 return elf_get_mem(elf, elf->header.section.offset + in elf_get_section_header()
221 (uint64_t)(idx * elf->header.section.entry_size)); in elf_get_section_header()
224 static inline int elf_get_section_info(const struct kmod_elf *elf, uint16_t idx, uint64_t *offset, … in elf_get_section_info() argument
226 const uint8_t *p = elf_get_section_header(elf, idx); in elf_get_section_info()
227 uint64_t min_size, off = p - elf->memory; in elf_get_section_info()
230 ELFDBG(elf, "no section at %"PRIu16"\n", idx); in elf_get_section_info()
238 elf_get_uint(elf, off + offsetof(typeof(*hdr), field), sizeof(hdr->field)) in elf_get_section_info()
240 if (elf->class & KMOD_ELF_32) { in elf_get_section_info()
254 || min_size > elf->size) { in elf_get_section_info()
255 ELFDBG(elf, "out-of-bounds: %"PRIu64" >= %"PRIu64" (ELF size)\n", in elf_get_section_info()
256 min_size, elf->size); in elf_get_section_info()
260 ELFDBG(elf, "section=%"PRIu16" is: offset=%"PRIu64" size=%"PRIu64" nameoff=%"PRIu32"\n", in elf_get_section_info()
266 static const char *elf_get_strings_section(const struct kmod_elf *elf, uint64_t *size) in elf_get_strings_section() argument
268 *size = elf->header.strings.size; in elf_get_strings_section()
269 return elf_get_mem(elf, elf->header.strings.offset); in elf_get_strings_section()
274 struct kmod_elf *elf; in kmod_elf_new() local
295 elf = malloc(sizeof(struct kmod_elf)); in kmod_elf_new()
296 if (elf == NULL) { in kmod_elf_new()
300 elf->memory = memory; in kmod_elf_new()
301 elf->changed = NULL; in kmod_elf_new()
302 elf->size = size; in kmod_elf_new()
303 elf->class = class; in kmod_elf_new()
306 elf_get_uint(elf, offsetof(typeof(*hdr), field), sizeof(hdr->field)) in kmod_elf_new()
309 elf->header.section.offset = READV(e_shoff); \ in kmod_elf_new()
310 elf->header.section.count = READV(e_shnum); \ in kmod_elf_new()
311 elf->header.section.entry_size = READV(e_shentsize); \ in kmod_elf_new()
312 elf->header.strings.section = READV(e_shstrndx); \ in kmod_elf_new()
313 elf->header.machine = READV(e_machine) in kmod_elf_new()
314 if (elf->class & KMOD_ELF_32) { in kmod_elf_new()
315 const Elf32_Ehdr *hdr _unused_ = elf_get_mem(elf, 0); in kmod_elf_new()
319 const Elf64_Ehdr *hdr _unused_ = elf_get_mem(elf, 0); in kmod_elf_new()
326 …ELFDBG(elf, "section: offset=%"PRIu64" count=%"PRIu16" entry_size=%"PRIu16" strings index=%"PRIu16… in kmod_elf_new()
327 elf->header.section.offset, in kmod_elf_new()
328 elf->header.section.count, in kmod_elf_new()
329 elf->header.section.entry_size, in kmod_elf_new()
330 elf->header.strings.section); in kmod_elf_new()
332 if (elf->header.section.entry_size != shdr_size) { in kmod_elf_new()
333 ELFDBG(elf, "unexpected section entry size: %"PRIu16", expected %"PRIu16"\n", in kmod_elf_new()
334 elf->header.section.entry_size, shdr_size); in kmod_elf_new()
337 shdrs_size = shdr_size * elf->header.section.count; in kmod_elf_new()
338 if (addu64_overflow(shdrs_size, elf->header.section.offset, &min_size) in kmod_elf_new()
339 || min_size > elf->size) { in kmod_elf_new()
340 ELFDBG(elf, "file is too short to hold sections\n"); in kmod_elf_new()
344 if (elf_get_section_info(elf, elf->header.strings.section, in kmod_elf_new()
345 &elf->header.strings.offset, in kmod_elf_new()
346 &elf->header.strings.size, in kmod_elf_new()
347 &elf->header.strings.nameoff) < 0) { in kmod_elf_new()
348 ELFDBG(elf, "could not get strings section\n"); in kmod_elf_new()
352 const char *s = elf_get_strings_section(elf, &slen); in kmod_elf_new()
354 ELFDBG(elf, "strings section does not ends with \\0\n"); in kmod_elf_new()
359 return elf; in kmod_elf_new()
362 free(elf); in kmod_elf_new()
367 void kmod_elf_unref(struct kmod_elf *elf) in kmod_elf_unref() argument
369 free(elf->changed); in kmod_elf_unref()
370 free(elf); in kmod_elf_unref()
373 const void *kmod_elf_get_memory(const struct kmod_elf *elf) in kmod_elf_get_memory() argument
375 return elf->memory; in kmod_elf_get_memory()
378 static int elf_find_section(const struct kmod_elf *elf, const char *section) in elf_find_section() argument
381 const char *names = elf_get_strings_section(elf, &nameslen); in elf_find_section()
384 for (i = 1; i < elf->header.section.count; i++) { in elf_find_section()
388 int err = elf_get_section_info(elf, i, &off, &size, &nameoff); in elf_find_section()
403 int kmod_elf_get_section(const struct kmod_elf *elf, const char *section, const void **buf, uint64_… in kmod_elf_get_section() argument
406 const char *names = elf_get_strings_section(elf, &nameslen); in kmod_elf_get_section()
412 for (i = 1; i < elf->header.section.count; i++) { in kmod_elf_get_section()
416 int err = elf_get_section_info(elf, i, &off, &size, &nameoff); in kmod_elf_get_section()
425 *buf = elf_get_mem(elf, off); in kmod_elf_get_section()
434 int kmod_elf_get_strings(const struct kmod_elf *elf, const char *section, char ***array) in kmod_elf_get_strings() argument
445 err = kmod_elf_get_section(elf, section, &buf, &size); in kmod_elf_get_strings()
506 int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_modversions() argument
519 if (elf->class & KMOD_ELF_32) in kmod_elf_get_modversions()
526 err = kmod_elf_get_section(elf, "__versions", &buf, &size); in kmod_elf_get_modversions()
538 off = (const uint8_t *)buf - elf->memory; in kmod_elf_get_modversions()
542 const char *symbol = elf_get_mem(elf, off + offcrc); in kmod_elf_get_modversions()
555 off = (const uint8_t *)buf - elf->memory; in kmod_elf_get_modversions()
558 uint64_t crc = elf_get_uint(elf, off, offcrc); in kmod_elf_get_modversions()
559 const char *symbol = elf_get_mem(elf, off + offcrc); in kmod_elf_get_modversions()
576 int kmod_elf_strip_section(struct kmod_elf *elf, const char *section) in kmod_elf_strip_section() argument
580 int idx = elf_find_section(elf, section); in kmod_elf_strip_section()
586 buf = elf_get_section_header(elf, idx); in kmod_elf_strip_section()
587 off = (const uint8_t *)buf - elf->memory; in kmod_elf_strip_section()
589 if (elf->class & KMOD_ELF_32) { in kmod_elf_strip_section()
597 val = elf_get_uint(elf, off, size); in kmod_elf_strip_section()
600 return elf_set_uint(elf, off, size, val); in kmod_elf_strip_section()
603 int kmod_elf_strip_vermagic(struct kmod_elf *elf) in kmod_elf_strip_vermagic() argument
610 err = kmod_elf_get_section(elf, ".modinfo", &buf, &size); in kmod_elf_strip_vermagic()
642 off = (const uint8_t *)s - elf->memory; in kmod_elf_strip_vermagic()
644 if (elf->changed == NULL) { in kmod_elf_strip_vermagic()
645 elf->changed = malloc(elf->size); in kmod_elf_strip_vermagic()
646 if (elf->changed == NULL) in kmod_elf_strip_vermagic()
648 memcpy(elf->changed, elf->memory, elf->size); in kmod_elf_strip_vermagic()
649 elf->memory = elf->changed; in kmod_elf_strip_vermagic()
650 ELFDBG(elf, "copied memory to allow writing.\n"); in kmod_elf_strip_vermagic()
654 ELFDBG(elf, "clear .modinfo vermagic \"%s\" (%zd bytes)\n", in kmod_elf_strip_vermagic()
656 memset(elf->changed + off, '\0', len); in kmod_elf_strip_vermagic()
660 ELFDBG(elf, "no vermagic found in .modinfo\n"); in kmod_elf_strip_vermagic()
665 static int kmod_elf_get_symbols_symtab(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_symbols_symtab() argument
676 err = kmod_elf_get_section(elf, "__ksymtab_strings", &buf, &size); in kmod_elf_get_symbols_symtab()
755 static uint64_t kmod_elf_resolve_crc(const struct kmod_elf *elf, uint64_t crc, uint16_t shndx) in kmod_elf_resolve_crc() argument
764 err = elf_get_section_info(elf, shndx, &off, &size, &nameoff); in kmod_elf_resolve_crc()
776 crc = elf_get_uint(elf, off + crc, sizeof(uint32_t)); in kmod_elf_resolve_crc()
781 int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_symbols() argument
792 err = kmod_elf_get_section(elf, ".strtab", &strtab, &strtablen); in kmod_elf_get_symbols()
794 ELFDBG(elf, "no .strtab found.\n"); in kmod_elf_get_symbols()
798 err = kmod_elf_get_section(elf, ".symtab", &symtab, &symtablen); in kmod_elf_get_symbols()
800 ELFDBG(elf, "no .symtab found.\n"); in kmod_elf_get_symbols()
804 if (elf->class & KMOD_ELF_32) in kmod_elf_get_symbols()
810 …ELFDBG(elf, "unexpected .symtab of length %"PRIu64", not multiple of %"PRIu64" as expected.\n", sy… in kmod_elf_get_symbols()
817 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_symbols()
818 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_symbols()
824 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_symbols()
826 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_symbols()
835 …ELFDBG(elf, ".strtab is %"PRIu64" bytes, but .symtab entry %d wants to access offset %"PRIu32".\n"… in kmod_elf_get_symbols()
839 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_symbols()
856 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_symbols()
857 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_symbols()
866 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_symbols()
868 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_symbols()
882 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_symbols()
887 if (elf->class & KMOD_ELF_32) in kmod_elf_get_symbols()
892 a[count].crc = kmod_elf_resolve_crc(elf, crc, shndx); in kmod_elf_get_symbols()
904 ELFDBG(elf, "Falling back to __ksymtab_strings!\n"); in kmod_elf_get_symbols()
905 return kmod_elf_get_symbols_symtab(elf, array); in kmod_elf_get_symbols()
908 static int kmod_elf_crc_find(const struct kmod_elf *elf, const void *versions, uint64_t versionslen… in kmod_elf_crc_find() argument
913 if (elf->class & KMOD_ELF_32) { in kmod_elf_crc_find()
923 off = (const uint8_t *)versions - elf->memory; in kmod_elf_crc_find()
925 const char *symbol = elf_get_mem(elf, off + i + crclen); in kmod_elf_crc_find()
928 *crc = elf_get_uint(elf, off + i, crclen); in kmod_elf_crc_find()
932 ELFDBG(elf, "could not find crc for symbol '%s'\n", name); in kmod_elf_crc_find()
943 int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_dependency_symbols() argument
955 err = kmod_elf_get_section(elf, "__versions", &versions, &versionslen); in kmod_elf_get_dependency_symbols()
962 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
972 …ELFDBG(elf, "unexpected __versions of length %"PRIu64", not multiple of %zd as expected.\n", versi… in kmod_elf_get_dependency_symbols()
978 err = kmod_elf_get_section(elf, ".strtab", &strtab, &strtablen); in kmod_elf_get_dependency_symbols()
980 ELFDBG(elf, "no .strtab found.\n"); in kmod_elf_get_dependency_symbols()
984 err = kmod_elf_get_section(elf, ".symtab", &symtab, &symtablen); in kmod_elf_get_dependency_symbols()
986 ELFDBG(elf, "no .symtab found.\n"); in kmod_elf_get_dependency_symbols()
990 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
996 …ELFDBG(elf, "unexpected .symtab of length %"PRIu64", not multiple of %"PRIu64" as expected.\n", sy… in kmod_elf_get_dependency_symbols()
1010 handle_register_symbols = (elf->header.machine == EM_SPARC || in kmod_elf_get_dependency_symbols()
1011 elf->header.machine == EM_SPARCV9); in kmod_elf_get_dependency_symbols()
1016 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_dependency_symbols()
1017 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_dependency_symbols()
1034 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_dependency_symbols()
1036 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
1053 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1068 …ELFDBG(elf, ".strtab is %"PRIu64" bytes, but .symtab entry %d wants to access offset %"PRIu32".\n"… in kmod_elf_get_dependency_symbols()
1074 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_dependency_symbols()
1076 ELFDBG(elf, "empty symbol name at index %"PRIu64"\n", i); in kmod_elf_get_dependency_symbols()
1083 idx = kmod_elf_crc_find(elf, versions, versionslen, name, &crc); in kmod_elf_get_dependency_symbols()
1091 ver_off = (const uint8_t *)versions - elf->memory; in kmod_elf_get_dependency_symbols()
1095 name = elf_get_mem(elf, ver_off + i * verlen + crclen); in kmod_elf_get_dependency_symbols()
1119 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_dependency_symbols()
1120 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_dependency_symbols()
1129 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_dependency_symbols()
1131 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
1148 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1162 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_dependency_symbols()
1164 ELFDBG(elf, "empty symbol name at index %"PRIu64"\n", i); in kmod_elf_get_dependency_symbols()
1168 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1196 ver_off = (const uint8_t *)versions - elf->memory; in kmod_elf_get_dependency_symbols()
1204 name = elf_get_mem(elf, ver_off + i * verlen + crclen); in kmod_elf_get_dependency_symbols()
1206 crc = elf_get_uint(elf, ver_off + i * verlen, crclen); in kmod_elf_get_dependency_symbols()