GPLv2 release
[centaur.git] / src / libelfu / modelops / dump.c
1 /* This file is part of centaur.
2  *
3  * centaur is free software: you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License 2 as
5  * published by the Free Software Foundation.
6
7  * centaur is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11
12  * You should have received a copy of the GNU General Public License
13  * along with centaur.  If not, see <http://www.gnu.org/licenses/>.
14  */
15
16 #include <assert.h>
17 #include <libelfu/libelfu.h>
18
19
20 static char* segmentTypeStr(Elf32_Word p_type)
21 {
22   switch(p_type) {
23     case PT_NULL: /* 0 */
24       return "NULL";
25     case PT_LOAD: /* 1 */
26       return "LOAD";
27     case PT_DYNAMIC: /* 2 */
28       return "DYNAMIC";
29     case PT_INTERP: /* 3 */
30       return "INTERP";
31     case PT_NOTE: /* 4 */
32       return "NOTE";
33     case PT_SHLIB: /* 5 */
34       return "SHLIB";
35     case PT_PHDR: /* 6 */
36       return "PHDR";
37     case PT_TLS: /* 7 */
38       return "TLS";
39     case PT_NUM: /* 8 */
40       return "NUM";
41     case PT_GNU_EH_FRAME: /* 0x6474e550 */
42       return "GNU_EH_FRAME";
43     case PT_GNU_STACK: /* 0x6474e551 */
44       return "GNU_STACK";
45     case PT_GNU_RELRO: /* 0x6474e552 */
46       return "GNU_RELRO";
47   }
48
49   return "-?-";
50 }
51
52 static char* sectionTypeStr(Elf32_Word sh_type)
53 {
54   switch(sh_type) {
55     case SHT_NULL: /* 0 */
56       return "NULL";
57     case SHT_PROGBITS: /* 1 */
58       return "PROGBITS";
59     case SHT_SYMTAB: /* 2 */
60       return "SYMTAB";
61     case SHT_STRTAB: /* 3 */
62       return "STRTAB";
63     case SHT_RELA: /* 4 */
64       return "RELA";
65     case SHT_HASH: /* 5 */
66       return "HASH";
67     case SHT_DYNAMIC: /* 6 */
68       return "DYNAMIC";
69     case SHT_NOTE: /* 7 */
70       return "NOTE";
71     case SHT_NOBITS: /* 8 */
72       return "NOBITS";
73     case SHT_REL: /* 9 */
74       return "REL";
75     case SHT_SHLIB: /* 10 */
76       return "SHLIB";
77     case SHT_DYNSYM: /* 11 */
78       return "DYNSYM";
79     case SHT_INIT_ARRAY: /* 14 */
80       return "INIT_ARRAY";
81     case SHT_FINI_ARRAY: /* 15 */
82       return "FINI_ARRAY";
83     case SHT_PREINIT_ARRAY: /* 16 */
84       return "PREINIT_ARRAY";
85     case SHT_GROUP: /* 17 */
86       return "SHT_GROUP";
87     case SHT_SYMTAB_SHNDX: /* 18 */
88       return "SYMTAB_SHNDX";
89     case SHT_NUM: /* 19 */
90       return "NUM";
91
92     case SHT_GNU_ATTRIBUTES: /* 0x6ffffff5 */
93       return "GNU_ATTRIBUTES";
94     case SHT_GNU_HASH: /* 0x6ffffff6 */
95       return "GNU_HASH";
96     case SHT_GNU_LIBLIST: /* 0x6ffffff7 */
97       return "GNU_LIBLIST";
98     case SHT_GNU_verdef: /* 0x6ffffffd */
99       return "GNU_verdef";
100     case SHT_GNU_verneed: /* 0x6ffffffe */
101       return "GNU_verneed";
102     case SHT_GNU_versym: /* 0x6fffffff */
103       return "GNU_versym";
104   }
105
106   return "-?-";
107 }
108
109
110
111
112 void elfu_mDumpPhdr(ElfuElf *me, ElfuPhdr *mp)
113 {
114   assert(me);
115   assert(mp);
116
117   ELFU_INFO("%12s %8x %8x %8x %8x %8x %8x %8x %8x\n",
118             segmentTypeStr(mp->phdr.p_type),
119             (unsigned)mp->phdr.p_type,
120             (unsigned)mp->phdr.p_offset,
121             (unsigned)mp->phdr.p_vaddr,
122             (unsigned)mp->phdr.p_paddr,
123             (unsigned)mp->phdr.p_filesz,
124             (unsigned)mp->phdr.p_memsz,
125             (unsigned)mp->phdr.p_flags,
126             (unsigned)mp->phdr.p_align);
127
128   if (!CIRCLEQ_EMPTY(&mp->childPhdrList)) {
129     ElfuPhdr *mpc;
130
131     ELFU_INFO("      -> Child PHDRs:\n");
132     CIRCLEQ_FOREACH(mpc, &mp->childPhdrList, elemChildPhdr) {
133       ELFU_INFO("        * %-8s @ %8x\n",
134                 segmentTypeStr(mpc->phdr.p_type),
135                 (unsigned)mpc->phdr.p_vaddr);
136     }
137   }
138
139   if (!CIRCLEQ_EMPTY(&mp->childScnList)) {
140     ElfuScn *msc;
141
142     ELFU_INFO("      -> Child sections:\n");
143     CIRCLEQ_FOREACH(msc, &mp->childScnList, elemChildScn) {
144       ELFU_INFO("        * %-17s @ %8x\n",
145                 elfu_mScnName(me, msc),
146                 (unsigned)msc->shdr.sh_addr);
147     }
148   }
149 }
150
151
152 void elfu_mDumpScn(ElfuElf *me, ElfuScn *ms)
153 {
154   char *namestr, *typestr, *linkstr, *infostr;
155
156   assert(me);
157   assert(ms);
158
159   namestr = elfu_mScnName(me, ms);
160   typestr = sectionTypeStr(ms->shdr.sh_type);
161   linkstr = ms->linkptr ? elfu_mScnName(me, ms->linkptr) : "";
162   infostr = ms->infoptr ? elfu_mScnName(me, ms->infoptr) : "";
163
164   ELFU_INFO("%-17s %-15s %8x %9x %8x %2x %2x %2d %-17s %-17s\n",
165             namestr,
166             typestr,
167             (unsigned)ms->shdr.sh_addr,
168             (unsigned)ms->shdr.sh_offset,
169             (unsigned)ms->shdr.sh_size,
170             (unsigned)ms->shdr.sh_entsize,
171             (unsigned)ms->shdr.sh_flags,
172             (unsigned)ms->shdr.sh_addralign,
173             linkstr,
174             infostr);
175 }
176
177
178 void elfu_mDumpEhdr(ElfuElf *me)
179 {
180   assert(me);
181
182   ELFU_INFO("ELF header:\n");
183   ELFU_INFO("   %d-bit ELF object\n", me->elfclass == ELFCLASS32 ? 32 : 64);
184
185   ELFU_INFO("   EHDR:\n");
186
187   ELFU_INFO("     e_type       %8x\n", me->ehdr.e_type);
188   ELFU_INFO("     e_machine    %8x\n", me->ehdr.e_machine);
189   ELFU_INFO("     e_version    %8x\n", me->ehdr.e_version);
190   ELFU_INFO("     e_entry      %8x\n", (unsigned)me->ehdr.e_entry);
191   ELFU_INFO("     e_phoff      %8x\n", (unsigned)me->ehdr.e_phoff);
192   ELFU_INFO("     e_shoff      %8x\n", (unsigned)me->ehdr.e_shoff);
193   ELFU_INFO("     e_flags      %8x\n", me->ehdr.e_flags);
194   ELFU_INFO("     e_ehsize     %8x\n", me->ehdr.e_ehsize);
195   ELFU_INFO("     e_phentsize  %8x\n", me->ehdr.e_phentsize);
196   ELFU_INFO("     e_shentsize  %8x\n", me->ehdr.e_shentsize);
197
198   ELFU_INFO("   shstrtab: %s\n", me->shstrtab ? elfu_mScnName(me, me->shstrtab) : "(none)");
199 }
200
201
202
203 static void* subScnDump(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
204 {
205   (void) aux1;
206   (void) aux2;
207
208   printf(" [%4d] ", elfu_mScnIndex(me, ms));
209   elfu_mDumpScn(me, ms);
210
211   return NULL;
212 }
213
214
215 void elfu_mDumpElf(ElfuElf *me)
216 {
217   ElfuPhdr *mp;
218   ElfuScn *ms;
219   size_t i;
220
221   assert(me);
222
223
224   elfu_mDumpEhdr(me);
225   ELFU_INFO("\n");
226
227
228   ELFU_INFO("Segments:\n");
229   ELFU_INFO("     #        (type)   p_type p_offset  p_vaddr  p_paddr p_filesz  p_memsz  p_flags  p_align\n");
230   ELFU_INFO("       |            |        |        |        |        |        |        |        |        \n");
231   i = 0;
232   CIRCLEQ_FOREACH(mp, &me->phdrList, elem) {
233     printf(" [%4d] ", i);
234     elfu_mDumpPhdr(me, mp);
235     i++;
236   }
237   ELFU_INFO("\n");
238
239
240   ELFU_INFO("Orphaned sections:\n");
241   CIRCLEQ_FOREACH(ms, &me->orphanScnList, elemChildScn) {
242     ELFU_INFO("        * %-17s @ %8x  offset %8x  size %8x\n",
243               elfu_mScnName(me, ms),
244               (unsigned)ms->shdr.sh_addr,
245               (unsigned)ms->shdr.sh_offset,
246               (unsigned)ms->shdr.sh_size);
247   }
248   ELFU_INFO("\n");
249
250
251   ELFU_INFO("Sections:\n");
252   ELFU_INFO("     #  Name              sh_type          sh_addr sh_offset  sh_size ES Fl Al sh_link           sh_info          \n");
253   ELFU_INFO("       |                 |               |        |         |        |  |  |  |                 |                 \n");
254   elfu_mScnForall(me, subScnDump, &i, NULL);
255   ELFU_INFO("\n");
256 }