diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-08-04 15:04:06 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-08-06 21:24:38 +0200 |
commit | f72617c002bbb5ebfa6283c692dbab782f5289cc (patch) | |
tree | 8d7b2b90fa1dcfa8eb59aabdbd48ce8e2c3f1012 /utils/imxtools/sbtools | |
parent | e4c9eaa7e8f247eb0623350e5d15d542ca665e17 (diff) | |
download | rockbox-f72617c002bbb5ebfa6283c692dbab782f5289cc.tar.gz rockbox-f72617c002bbb5ebfa6283c692dbab782f5289cc.zip |
sbtools: elf library can now load global symbols
Change-Id: I4d9f38ce31e65542d6ab192158bff52b6fad8f09
Diffstat (limited to 'utils/imxtools/sbtools')
-rw-r--r-- | utils/imxtools/sbtools/elf.c | 185 | ||||
-rw-r--r-- | utils/imxtools/sbtools/elf.h | 19 | ||||
-rw-r--r-- | utils/imxtools/sbtools/elftosb1.c | 2 |
3 files changed, 171 insertions, 35 deletions
diff --git a/utils/imxtools/sbtools/elf.c b/utils/imxtools/sbtools/elf.c index a0b249570a..5d5e1a786c 100644 --- a/utils/imxtools/sbtools/elf.c +++ b/utils/imxtools/sbtools/elf.c | |||
@@ -96,6 +96,7 @@ typedef struct | |||
96 | #define EF_ARM_HASENTRY 0x00000002 | 96 | #define EF_ARM_HASENTRY 0x00000002 |
97 | 97 | ||
98 | #define SHN_UNDEF 0 /* Undefined section */ | 98 | #define SHN_UNDEF 0 /* Undefined section */ |
99 | #define SHN_ABS 0xfff1 /* Associated symbol is absolute */ | ||
99 | 100 | ||
100 | typedef struct | 101 | typedef struct |
101 | { | 102 | { |
@@ -154,6 +155,44 @@ typedef struct | |||
154 | #define PF_W (1 << 1) /* Segment is writable */ | 155 | #define PF_W (1 << 1) /* Segment is writable */ |
155 | #define PF_R (1 << 2) /* Segment is readable */ | 156 | #define PF_R (1 << 2) /* Segment is readable */ |
156 | 157 | ||
158 | typedef struct | ||
159 | { | ||
160 | Elf32_Word st_name; /* Symbol name (string tbl index) */ | ||
161 | Elf32_Addr st_value; /* Symbol value */ | ||
162 | Elf32_Word st_size; /* Symbol size */ | ||
163 | unsigned char st_info; /* Symbol type and binding */ | ||
164 | unsigned char st_other; /* Symbol visibility */ | ||
165 | Elf32_Section st_shndx; /* Section index */ | ||
166 | }Elf32_Sym; | ||
167 | |||
168 | #define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) | ||
169 | #define ELF32_ST_TYPE(val) ((val) & 0xf) | ||
170 | #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) | ||
171 | |||
172 | #define STB_LOCAL 0 /* Local symbol */ | ||
173 | #define STB_GLOBAL 1 /* Global symbol */ | ||
174 | #define STB_WEAK 2 /* Weak symbol */ | ||
175 | #define STB_NUM 3 /* Number of defined types. */ | ||
176 | #define STB_LOOS 10 /* Start of OS-specific */ | ||
177 | #define STB_GNU_UNIQUE 10 /* Unique symbol. */ | ||
178 | #define STB_HIOS 12 /* End of OS-specific */ | ||
179 | #define STB_LOPROC 13 /* Start of processor-specific */ | ||
180 | #define STB_HIPROC 15 /* End of processor-specific */ | ||
181 | |||
182 | #define STT_NOTYPE 0 /* Symbol type is unspecified */ | ||
183 | #define STT_OBJECT 1 /* Symbol is a data object */ | ||
184 | #define STT_FUNC 2 /* Symbol is a code object */ | ||
185 | #define STT_SECTION 3 /* Symbol associated with a section */ | ||
186 | #define STT_FILE 4 /* Symbol's name is file name */ | ||
187 | #define STT_COMMON 5 /* Symbol is a common data object */ | ||
188 | #define STT_TLS 6 /* Symbol is thread-local data object*/ | ||
189 | #define STT_NUM 7 /* Number of defined types. */ | ||
190 | #define STT_LOOS 10 /* Start of OS-specific */ | ||
191 | #define STT_GNU_IFUNC 10 /* Symbol is indirect code object */ | ||
192 | #define STT_HIOS 12 /* End of OS-specific */ | ||
193 | #define STT_LOPROC 13 /* Start of processor-specific */ | ||
194 | #define STT_HIPROC 15 /* End of processor-specific */ | ||
195 | |||
157 | void elf_init(struct elf_params_t *params) | 196 | void elf_init(struct elf_params_t *params) |
158 | { | 197 | { |
159 | memset(params, 0, sizeof(struct elf_params_t)); | 198 | memset(params, 0, sizeof(struct elf_params_t)); |
@@ -164,6 +203,7 @@ extern void *xmalloc(size_t s); | |||
164 | static struct elf_section_t *elf_add_section(struct elf_params_t *params) | 203 | static struct elf_section_t *elf_add_section(struct elf_params_t *params) |
165 | { | 204 | { |
166 | struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t)); | 205 | struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t)); |
206 | memset(sec, 0, sizeof(struct elf_section_t)); | ||
167 | if(params->first_section == NULL) | 207 | if(params->first_section == NULL) |
168 | params->first_section = params->last_section = sec; | 208 | params->first_section = params->last_section = sec; |
169 | else | 209 | else |
@@ -176,6 +216,22 @@ static struct elf_section_t *elf_add_section(struct elf_params_t *params) | |||
176 | return sec; | 216 | return sec; |
177 | } | 217 | } |
178 | 218 | ||
219 | static struct elf_symbol_t *elf_add_symbol(struct elf_params_t *params) | ||
220 | { | ||
221 | struct elf_symbol_t *sym = xmalloc(sizeof(struct elf_symbol_t)); | ||
222 | memset(sym, 0, sizeof(struct elf_symbol_t)); | ||
223 | if(params->first_symbol == NULL) | ||
224 | params->first_symbol = params->last_symbol = sym; | ||
225 | else | ||
226 | { | ||
227 | params->last_symbol->next = sym; | ||
228 | params->last_symbol = sym; | ||
229 | } | ||
230 | sym->next = NULL; | ||
231 | |||
232 | return sym; | ||
233 | } | ||
234 | |||
179 | static struct elf_segment_t *elf_add_segment(struct elf_params_t *params) | 235 | static struct elf_segment_t *elf_add_segment(struct elf_params_t *params) |
180 | { | 236 | { |
181 | struct elf_segment_t *seg = xmalloc(sizeof(struct elf_section_t)); | 237 | struct elf_segment_t *seg = xmalloc(sizeof(struct elf_section_t)); |
@@ -551,6 +607,18 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, | |||
551 | free(strtbl_content); | 607 | free(strtbl_content); |
552 | } | 608 | } |
553 | 609 | ||
610 | static void *elf_load_section(Elf32_Shdr *sh, elf_read_fn_t read, elf_printf_fn_t printf, void *user) | ||
611 | { | ||
612 | void *data = xmalloc(sh->sh_size); | ||
613 | if(!read(user, sh->sh_offset, data, sh->sh_size)) | ||
614 | { | ||
615 | free(data); | ||
616 | printf(user, true, "error reading elf section data\n"); | ||
617 | return NULL; | ||
618 | } | ||
619 | return data; | ||
620 | } | ||
621 | |||
554 | bool elf_guess(elf_read_fn_t read, void *user) | 622 | bool elf_guess(elf_read_fn_t read, void *user) |
555 | { | 623 | { |
556 | /* read header */ | 624 | /* read header */ |
@@ -598,56 +666,94 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
598 | error_printf("invalid elf file: section header size mismatch\n"); | 666 | error_printf("invalid elf file: section header size mismatch\n"); |
599 | elf_set_start_addr(params, ehdr.e_entry); | 667 | elf_set_start_addr(params, ehdr.e_entry); |
600 | 668 | ||
601 | char *strtab = NULL; | ||
602 | if(ehdr.e_shstrndx != SHN_UNDEF) | ||
603 | { | ||
604 | Elf32_Shdr shstrtab; | ||
605 | if(read(user, ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize, | ||
606 | &shstrtab, sizeof(shstrtab))) | ||
607 | { | ||
608 | strtab = xmalloc(shstrtab.sh_size); | ||
609 | if(!read(user, shstrtab.sh_offset, strtab, shstrtab.sh_size)) | ||
610 | { | ||
611 | free(strtab); | ||
612 | strtab = NULL; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | /* run through sections */ | 669 | /* run through sections */ |
617 | printf(user, false, "ELF file:\n"); | 670 | printf(user, false, "ELF file:\n"); |
671 | Elf32_Shdr *shdr = xmalloc(sizeof(Elf32_Shdr) * ehdr.e_shnum); | ||
672 | if(!read(user, ehdr.e_shoff, shdr, sizeof(Elf32_Shdr) * ehdr.e_shnum)) | ||
673 | { | ||
674 | printf(user, true, "cannot read elf section headers\n"); | ||
675 | return false; | ||
676 | } | ||
677 | char *strtab = elf_load_section(&shdr[ehdr.e_shstrndx], read, printf, user); | ||
678 | if(!strtab) | ||
679 | printf(user, false, "elf file has no valid section string table\n"); | ||
618 | for(int i = 1; i < ehdr.e_shnum; i++) | 680 | for(int i = 1; i < ehdr.e_shnum; i++) |
619 | { | 681 | { |
620 | uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize; | 682 | const char *sec_name = &strtab[shdr[i].sh_name]; |
621 | Elf32_Shdr shdr; | 683 | if(strtab == NULL) |
622 | memset(&shdr, 0, sizeof(shdr)); | 684 | sec_name = NULL; |
623 | if(!read(user, off, &shdr, sizeof(shdr))) | ||
624 | error_printf("error reading elf section header"); | ||
625 | 685 | ||
626 | if(shdr.sh_type == SHT_PROGBITS && shdr.sh_flags & SHF_ALLOC) | 686 | if(shdr[i].sh_type == SHT_PROGBITS && shdr[i].sh_flags & SHF_ALLOC) |
627 | { | 687 | { |
628 | void *data = xmalloc(shdr.sh_size); | 688 | void *data = elf_load_section(&shdr[i], read, printf, user); |
629 | if(!read(user, shdr.sh_offset, data, shdr.sh_size)) | 689 | if(!data) |
630 | error_printf("error read self section data\n"); | 690 | { |
631 | elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data, &strtab[shdr.sh_name]); | 691 | printf(user, true, "cannot read elf section %s\n", sec_name); |
692 | goto Lerr; | ||
693 | } | ||
694 | elf_add_load_section(params, shdr[i].sh_addr, shdr[i].sh_size, data, sec_name); | ||
632 | free(data); | 695 | free(data); |
633 | 696 | ||
634 | if(strtab) | 697 | printf(user, false, "create load segment for %s\n", sec_name); |
635 | printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]); | 698 | } |
699 | else if(shdr[i].sh_type == SHT_NOBITS && shdr[i].sh_flags & SHF_ALLOC) | ||
700 | { | ||
701 | elf_add_fill_section(params, shdr[i].sh_addr, shdr[i].sh_size, 0, sec_name); | ||
702 | printf(user, false, "create fill segment for %s\n", sec_name); | ||
636 | } | 703 | } |
637 | else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC) | 704 | else if(shdr[i].sh_type == SHT_SYMTAB) |
638 | { | 705 | { |
639 | elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0, &strtab[shdr.sh_name]); | 706 | // load string table |
640 | if(strtab) | 707 | char *symstrtab = elf_load_section(&shdr[shdr[i].sh_link], read, printf, user); |
641 | printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]); | 708 | if(!symstrtab) |
709 | { | ||
710 | printf(user, true, "cannot load string table for symbol table %s\n", sec_name); | ||
711 | goto Lerr; | ||
712 | } | ||
713 | // load symbol table data | ||
714 | Elf32_Sym *symdata = elf_load_section(&shdr[i], read, printf, user); | ||
715 | if(!symdata) | ||
716 | { | ||
717 | printf(user, true, "cannot read elf section %s\n", sec_name); | ||
718 | free(symstrtab); | ||
719 | goto Lerr; | ||
720 | } | ||
721 | // load symbols (only global ones) | ||
722 | int nr_symbols = shdr[i].sh_size / sizeof(Elf32_Sym); | ||
723 | for(int j = shdr[i].sh_info; j < nr_symbols; j++) | ||
724 | { | ||
725 | if(ELF32_ST_BIND(symdata[j].st_info) != STB_GLOBAL) | ||
726 | continue; | ||
727 | int type = ELF32_ST_TYPE(symdata[j].st_info); | ||
728 | if(type != STT_NOTYPE && type != STT_FUNC && type != STT_OBJECT) | ||
729 | continue; | ||
730 | if(symdata[j].st_shndx == SHN_UNDEF) | ||
731 | continue; | ||
732 | struct elf_symbol_t *sym = elf_add_symbol(params); | ||
733 | sym->name = strdup(&symstrtab[symdata[j].st_name]); | ||
734 | sym->addr = symdata[j].st_value; | ||
735 | sym->size = symdata[j].st_size; | ||
736 | sym->section = strdup(&strtab[shdr[symdata[j].st_shndx].sh_name]); | ||
737 | switch(type) | ||
738 | { | ||
739 | case STT_FUNC: sym->type = ESYT_FUNC; break; | ||
740 | case STT_OBJECT: sym->type = ESYT_OBJECT; break; | ||
741 | case STT_NOTYPE: default: sym->type = ESYT_NOTYPE; break; | ||
742 | } | ||
743 | printf(user, false, "add symbol %s at %#x, type %d, size %d, section %s\n", | ||
744 | sym->name, sym->addr, sym->type, sym->size, sym->section); | ||
745 | } | ||
746 | free(symdata); | ||
747 | free(symstrtab); | ||
642 | } | 748 | } |
643 | else | 749 | else |
644 | { | 750 | { |
645 | if(strtab) | 751 | printf(user, false, "filter out %s, type %d\n", sec_name, shdr[i].sh_type); |
646 | printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type); | ||
647 | } | 752 | } |
648 | 753 | ||
649 | } | 754 | } |
650 | free(strtab); | 755 | free(strtab); |
756 | free(shdr); | ||
651 | /* run through segments */ | 757 | /* run through segments */ |
652 | for(int i = 1; i < ehdr.e_phnum; i++) | 758 | for(int i = 1; i < ehdr.e_phnum; i++) |
653 | { | 759 | { |
@@ -668,6 +774,10 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
668 | } | 774 | } |
669 | 775 | ||
670 | return true; | 776 | return true; |
777 | Lerr: | ||
778 | free(strtab); | ||
779 | free(shdr); | ||
780 | return false; | ||
671 | } | 781 | } |
672 | 782 | ||
673 | uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr) | 783 | uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr) |
@@ -742,6 +852,15 @@ void elf_release(struct elf_params_t *params) | |||
742 | free(seg); | 852 | free(seg); |
743 | seg = next_seg; | 853 | seg = next_seg; |
744 | } | 854 | } |
855 | struct elf_symbol_t *sym = params->first_symbol; | ||
856 | while(sym) | ||
857 | { | ||
858 | free(sym->name); | ||
859 | free(sym->section); | ||
860 | struct elf_symbol_t *next_sym = sym->next; | ||
861 | free(sym); | ||
862 | sym = next_sym; | ||
863 | } | ||
745 | } | 864 | } |
746 | 865 | ||
747 | void elf_std_printf(void *user, bool error, const char *fmt, ...) | 866 | void elf_std_printf(void *user, bool error, const char *fmt, ...) |
diff --git a/utils/imxtools/sbtools/elf.h b/utils/imxtools/sbtools/elf.h index cabe764e45..09cbe251a1 100644 --- a/utils/imxtools/sbtools/elf.h +++ b/utils/imxtools/sbtools/elf.h | |||
@@ -61,6 +61,23 @@ struct elf_segment_t | |||
61 | struct elf_segment_t *next; | 61 | struct elf_segment_t *next; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | enum elf_symbol_type_t | ||
65 | { | ||
66 | ESYT_NOTYPE, | ||
67 | ESYT_OBJECT, | ||
68 | ESYT_FUNC, | ||
69 | }; | ||
70 | |||
71 | struct elf_symbol_t | ||
72 | { | ||
73 | char *name; | ||
74 | uint32_t addr; | ||
75 | uint32_t size; | ||
76 | enum elf_symbol_type_t type; | ||
77 | char *section; | ||
78 | struct elf_symbol_t *next; | ||
79 | }; | ||
80 | |||
64 | struct elf_params_t | 81 | struct elf_params_t |
65 | { | 82 | { |
66 | bool has_start_addr; | 83 | bool has_start_addr; |
@@ -69,6 +86,8 @@ struct elf_params_t | |||
69 | struct elf_section_t *last_section; | 86 | struct elf_section_t *last_section; |
70 | struct elf_segment_t *first_segment; | 87 | struct elf_segment_t *first_segment; |
71 | struct elf_segment_t *last_segment; | 88 | struct elf_segment_t *last_segment; |
89 | struct elf_symbol_t *first_symbol; | ||
90 | struct elf_symbol_t *last_symbol; | ||
72 | }; | 91 | }; |
73 | 92 | ||
74 | typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count); | 93 | typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count); |
diff --git a/utils/imxtools/sbtools/elftosb1.c b/utils/imxtools/sbtools/elftosb1.c index be9201c396..79b7621844 100644 --- a/utils/imxtools/sbtools/elftosb1.c +++ b/utils/imxtools/sbtools/elftosb1.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #define _ISOC99_SOURCE | ||
23 | #define _POSIX_C_SOURCE 200809L /* for strdup */ | ||
24 | #include <stdio.h> | 22 | #include <stdio.h> |
25 | #include <errno.h> | 23 | #include <errno.h> |
26 | #include <stdlib.h> | 24 | #include <stdlib.h> |