Lines Matching refs:elf
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
290 elf = malloc(sizeof(struct kmod_elf)); in kmod_elf_new()
291 if (elf == NULL) { in kmod_elf_new()
295 elf->memory = memory; in kmod_elf_new()
296 elf->changed = NULL; in kmod_elf_new()
297 elf->size = size; in kmod_elf_new()
298 elf->class = class; in kmod_elf_new()
301 elf_get_uint(elf, offsetof(typeof(*hdr), field), sizeof(hdr->field)) in kmod_elf_new()
304 elf->header.section.offset = READV(e_shoff); \ in kmod_elf_new()
305 elf->header.section.count = READV(e_shnum); \ in kmod_elf_new()
306 elf->header.section.entry_size = READV(e_shentsize); \ in kmod_elf_new()
307 elf->header.strings.section = READV(e_shstrndx); \ in kmod_elf_new()
308 elf->header.machine = READV(e_machine) in kmod_elf_new()
309 if (elf->class & KMOD_ELF_32) { in kmod_elf_new()
310 const Elf32_Ehdr *hdr _unused_ = elf_get_mem(elf, 0); in kmod_elf_new()
314 const Elf64_Ehdr *hdr _unused_ = elf_get_mem(elf, 0); in kmod_elf_new()
321 …ELFDBG(elf, "section: offset=%"PRIu64" count=%"PRIu16" entry_size=%"PRIu16" strings index=%"PRIu16… in kmod_elf_new()
322 elf->header.section.offset, in kmod_elf_new()
323 elf->header.section.count, in kmod_elf_new()
324 elf->header.section.entry_size, in kmod_elf_new()
325 elf->header.strings.section); in kmod_elf_new()
327 if (elf->header.section.entry_size != shdr_size) { in kmod_elf_new()
328 ELFDBG(elf, "unexpected section entry size: %"PRIu16", expected %"PRIu16"\n", in kmod_elf_new()
329 elf->header.section.entry_size, shdr_size); in kmod_elf_new()
332 shdrs_size = shdr_size * elf->header.section.count; in kmod_elf_new()
333 if (addu64_overflow(shdrs_size, elf->header.section.offset, &min_size) in kmod_elf_new()
334 || min_size > elf->size) { in kmod_elf_new()
335 ELFDBG(elf, "file is too short to hold sections\n"); in kmod_elf_new()
339 if (elf_get_section_info(elf, elf->header.strings.section, in kmod_elf_new()
340 &elf->header.strings.offset, in kmod_elf_new()
341 &elf->header.strings.size, in kmod_elf_new()
342 &elf->header.strings.nameoff) < 0) { in kmod_elf_new()
343 ELFDBG(elf, "could not get strings section\n"); in kmod_elf_new()
347 const char *s = elf_get_strings_section(elf, &slen); in kmod_elf_new()
349 ELFDBG(elf, "strings section does not ends with \\0\n"); in kmod_elf_new()
354 return elf; in kmod_elf_new()
357 free(elf); in kmod_elf_new()
362 void kmod_elf_unref(struct kmod_elf *elf) in kmod_elf_unref() argument
364 free(elf->changed); in kmod_elf_unref()
365 free(elf); in kmod_elf_unref()
368 const void *kmod_elf_get_memory(const struct kmod_elf *elf) in kmod_elf_get_memory() argument
370 return elf->memory; in kmod_elf_get_memory()
373 static int elf_find_section(const struct kmod_elf *elf, const char *section) in elf_find_section() argument
376 const char *names = elf_get_strings_section(elf, &nameslen); in elf_find_section()
379 for (i = 1; i < elf->header.section.count; i++) { in elf_find_section()
383 int err = elf_get_section_info(elf, i, &off, &size, &nameoff); in elf_find_section()
398 int kmod_elf_get_section(const struct kmod_elf *elf, const char *section, const void **buf, uint64_… in kmod_elf_get_section() argument
401 const char *names = elf_get_strings_section(elf, &nameslen); in kmod_elf_get_section()
407 for (i = 1; i < elf->header.section.count; i++) { in kmod_elf_get_section()
411 int err = elf_get_section_info(elf, i, &off, &size, &nameoff); in kmod_elf_get_section()
420 *buf = elf_get_mem(elf, off); in kmod_elf_get_section()
429 int kmod_elf_get_strings(const struct kmod_elf *elf, const char *section, char ***array) in kmod_elf_get_strings() argument
440 err = kmod_elf_get_section(elf, section, &buf, &size); in kmod_elf_get_strings()
501 int kmod_elf_get_modversions(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_modversions() argument
514 if (elf->class & KMOD_ELF_32) in kmod_elf_get_modversions()
521 err = kmod_elf_get_section(elf, "__versions", &buf, &size); in kmod_elf_get_modversions()
533 off = (const uint8_t *)buf - elf->memory; in kmod_elf_get_modversions()
537 const char *symbol = elf_get_mem(elf, off + offcrc); in kmod_elf_get_modversions()
550 off = (const uint8_t *)buf - elf->memory; in kmod_elf_get_modversions()
553 uint64_t crc = elf_get_uint(elf, off, offcrc); in kmod_elf_get_modversions()
554 const char *symbol = elf_get_mem(elf, off + offcrc); in kmod_elf_get_modversions()
571 int kmod_elf_strip_section(struct kmod_elf *elf, const char *section) in kmod_elf_strip_section() argument
575 int idx = elf_find_section(elf, section); in kmod_elf_strip_section()
581 buf = elf_get_section_header(elf, idx); in kmod_elf_strip_section()
582 off = (const uint8_t *)buf - elf->memory; in kmod_elf_strip_section()
584 if (elf->class & KMOD_ELF_32) { in kmod_elf_strip_section()
592 val = elf_get_uint(elf, off, size); in kmod_elf_strip_section()
595 return elf_set_uint(elf, off, size, val); in kmod_elf_strip_section()
598 int kmod_elf_strip_vermagic(struct kmod_elf *elf) in kmod_elf_strip_vermagic() argument
605 err = kmod_elf_get_section(elf, ".modinfo", &buf, &size); in kmod_elf_strip_vermagic()
637 off = (const uint8_t *)s - elf->memory; in kmod_elf_strip_vermagic()
639 if (elf->changed == NULL) { in kmod_elf_strip_vermagic()
640 elf->changed = malloc(elf->size); in kmod_elf_strip_vermagic()
641 if (elf->changed == NULL) in kmod_elf_strip_vermagic()
643 memcpy(elf->changed, elf->memory, elf->size); in kmod_elf_strip_vermagic()
644 elf->memory = elf->changed; in kmod_elf_strip_vermagic()
645 ELFDBG(elf, "copied memory to allow writing.\n"); in kmod_elf_strip_vermagic()
649 ELFDBG(elf, "clear .modinfo vermagic \"%s\" (%zd bytes)\n", in kmod_elf_strip_vermagic()
651 memset(elf->changed + off, '\0', len); in kmod_elf_strip_vermagic()
655 ELFDBG(elf, "no vermagic found in .modinfo\n"); in kmod_elf_strip_vermagic()
660 static int kmod_elf_get_symbols_symtab(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_symbols_symtab() argument
671 err = kmod_elf_get_section(elf, "__ksymtab_strings", &buf, &size); in kmod_elf_get_symbols_symtab()
750 static uint64_t kmod_elf_resolve_crc(const struct kmod_elf *elf, uint64_t crc, uint16_t shndx) in kmod_elf_resolve_crc() argument
759 err = elf_get_section_info(elf, shndx, &off, &size, &nameoff); in kmod_elf_resolve_crc()
771 crc = elf_get_uint(elf, off + crc, sizeof(uint32_t)); in kmod_elf_resolve_crc()
776 int kmod_elf_get_symbols(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_symbols() argument
787 err = kmod_elf_get_section(elf, ".strtab", &strtab, &strtablen); in kmod_elf_get_symbols()
789 ELFDBG(elf, "no .strtab found.\n"); in kmod_elf_get_symbols()
793 err = kmod_elf_get_section(elf, ".symtab", &symtab, &symtablen); in kmod_elf_get_symbols()
795 ELFDBG(elf, "no .symtab found.\n"); in kmod_elf_get_symbols()
799 if (elf->class & KMOD_ELF_32) in kmod_elf_get_symbols()
805 …ELFDBG(elf, "unexpected .symtab of length %"PRIu64", not multiple of %"PRIu64" as expected.\n", sy… in kmod_elf_get_symbols()
812 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_symbols()
813 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_symbols()
819 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_symbols()
821 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_symbols()
830 …ELFDBG(elf, ".strtab is %"PRIu64" bytes, but .symtab entry %d wants to access offset %"PRIu32".\n"… in kmod_elf_get_symbols()
834 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_symbols()
851 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_symbols()
852 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_symbols()
861 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_symbols()
863 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_symbols()
877 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_symbols()
882 if (elf->class & KMOD_ELF_32) in kmod_elf_get_symbols()
887 a[count].crc = kmod_elf_resolve_crc(elf, crc, shndx); in kmod_elf_get_symbols()
899 ELFDBG(elf, "Falling back to __ksymtab_strings!\n"); in kmod_elf_get_symbols()
900 return kmod_elf_get_symbols_symtab(elf, array); in kmod_elf_get_symbols()
903 static int kmod_elf_crc_find(const struct kmod_elf *elf, const void *versions, uint64_t versionslen… in kmod_elf_crc_find() argument
908 if (elf->class & KMOD_ELF_32) { in kmod_elf_crc_find()
918 off = (const uint8_t *)versions - elf->memory; in kmod_elf_crc_find()
920 const char *symbol = elf_get_mem(elf, off + i + crclen); in kmod_elf_crc_find()
923 *crc = elf_get_uint(elf, off + i, crclen); in kmod_elf_crc_find()
927 ELFDBG(elf, "could not find crc for symbol '%s'\n", name); in kmod_elf_crc_find()
938 int kmod_elf_get_dependency_symbols(const struct kmod_elf *elf, struct kmod_modversion **array) in kmod_elf_get_dependency_symbols() argument
950 err = kmod_elf_get_section(elf, "__versions", &versions, &versionslen); in kmod_elf_get_dependency_symbols()
957 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
967 …ELFDBG(elf, "unexpected __versions of length %"PRIu64", not multiple of %zd as expected.\n", versi… in kmod_elf_get_dependency_symbols()
973 err = kmod_elf_get_section(elf, ".strtab", &strtab, &strtablen); in kmod_elf_get_dependency_symbols()
975 ELFDBG(elf, "no .strtab found.\n"); in kmod_elf_get_dependency_symbols()
979 err = kmod_elf_get_section(elf, ".symtab", &symtab, &symtablen); in kmod_elf_get_dependency_symbols()
981 ELFDBG(elf, "no .symtab found.\n"); in kmod_elf_get_dependency_symbols()
985 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
991 …ELFDBG(elf, "unexpected .symtab of length %"PRIu64", not multiple of %"PRIu64" as expected.\n", sy… in kmod_elf_get_dependency_symbols()
1005 handle_register_symbols = (elf->header.machine == EM_SPARC || in kmod_elf_get_dependency_symbols()
1006 elf->header.machine == EM_SPARCV9); in kmod_elf_get_dependency_symbols()
1011 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_dependency_symbols()
1012 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_dependency_symbols()
1029 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_dependency_symbols()
1031 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
1048 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1063 …ELFDBG(elf, ".strtab is %"PRIu64" bytes, but .symtab entry %d wants to access offset %"PRIu32".\n"… in kmod_elf_get_dependency_symbols()
1069 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_dependency_symbols()
1071 ELFDBG(elf, "empty symbol name at index %"PRIu64"\n", i); in kmod_elf_get_dependency_symbols()
1078 idx = kmod_elf_crc_find(elf, versions, versionslen, name, &crc); in kmod_elf_get_dependency_symbols()
1086 ver_off = (const uint8_t *)versions - elf->memory; in kmod_elf_get_dependency_symbols()
1090 name = elf_get_mem(elf, ver_off + i * verlen + crclen); in kmod_elf_get_dependency_symbols()
1114 str_off = (const uint8_t *)strtab - elf->memory; in kmod_elf_get_dependency_symbols()
1115 sym_off = (const uint8_t *)symtab - elf->memory + symlen; in kmod_elf_get_dependency_symbols()
1124 elf_get_uint(elf, sym_off + offsetof(typeof(*s), field),\ in kmod_elf_get_dependency_symbols()
1126 if (elf->class & KMOD_ELF_32) { in kmod_elf_get_dependency_symbols()
1143 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1157 name = elf_get_mem(elf, str_off + name_off); in kmod_elf_get_dependency_symbols()
1159 ELFDBG(elf, "empty symbol name at index %"PRIu64"\n", i); in kmod_elf_get_dependency_symbols()
1163 if (elf->class & KMOD_ELF_32) in kmod_elf_get_dependency_symbols()
1191 ver_off = (const uint8_t *)versions - elf->memory; in kmod_elf_get_dependency_symbols()
1199 name = elf_get_mem(elf, ver_off + i * verlen + crclen); in kmod_elf_get_dependency_symbols()
1201 crc = elf_get_uint(elf, ver_off + i * verlen, crclen); in kmod_elf_get_dependency_symbols()