Cleanup whitespace in the Makefile.am
[memprof.git] / src / elfparser.c
blob86a3f342570d17b6948a4c1d82c0dd863d0cf40a
1 /* Sysprof -- Sampling, systemwide CPU profiler
2 * Copyright 2006, 2007, Soeren Sandmann
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include <stdlib.h>
19 #include <string.h>
20 #include <elf.h>
21 #include <sys/mman.h>
22 #include "binparser.h"
23 #include "elfparser.h"
25 typedef struct Section Section;
27 struct ElfSym
29 gulong offset;
30 gulong address;
33 struct Section
35 const gchar * name;
36 gsize offset;
37 gsize size;
38 gboolean allocated;
39 gulong load_address;
40 guint type;
43 struct ElfParser
45 BinParser * parser;
47 BinRecord * header;
48 BinRecord * strtab_format;
49 BinRecord * shn_entry;
50 BinRecord * sym_format;
52 int n_sections;
53 Section ** sections;
55 int n_symbols;
56 ElfSym * symbols;
57 gsize sym_strings;
59 GMappedFile * file;
61 const Section * text_section;
64 static gboolean parse_elf_signature (const guchar *data, gsize length,
65 gboolean *is_64, gboolean *is_be);
66 static void make_formats (ElfParser *parser, gboolean is_64);
68 static const char *
69 get_string_indirect (BinParser *parser,
70 BinRecord *record,
71 const char *name,
72 gsize str_table)
74 const char *result = NULL;
75 gsize index;
77 bin_parser_save (parser);
79 index = bin_parser_get_uint_field (parser, record, name);
81 bin_parser_set_offset (parser, str_table + index);
83 result = bin_parser_get_string (parser);
85 bin_parser_restore (parser);
87 return result;
90 static Section *
91 section_new (BinParser *parser,
92 BinRecord *record,
93 gsize name_table)
95 Section *section = g_new (Section, 1);
96 guint64 flags;
98 section->name = get_string_indirect (parser, record, "sh_name", name_table);
99 section->size = bin_parser_get_uint_field (parser, record, "sh_size");
100 section->offset = bin_parser_get_uint_field (parser, record, "sh_offset");
102 flags = bin_parser_get_uint_field (parser, record, "sh_flags");
103 section->allocated = !!(flags & SHF_ALLOC);
105 if (section->allocated)
107 section->load_address = bin_parser_get_uint_field (
108 parser, record, "sh_addr");
110 else
112 section->load_address = 0;
115 section->type = bin_parser_get_uint_field (parser, record, "sh_type");
117 return section;
120 static void
121 section_free (Section *section)
123 g_free (section);
126 static const Section *
127 find_section (ElfParser *parser,
128 const char *name,
129 guint type)
131 int i;
133 for (i = 0; i < parser->n_sections; ++i)
135 Section *section = parser->sections[i];
137 if (strcmp (section->name, name) == 0 && section->type == type)
138 return section;
141 return NULL;
144 ElfParser *
145 elf_parser_new_from_data (const guchar *data,
146 gsize length)
148 ElfParser *parser;
149 gboolean is_64, is_big_endian;
150 int section_names_idx;
151 gsize section_names;
152 gsize section_headers;
153 int i;
155 if (!parse_elf_signature (data, length, &is_64, &is_big_endian))
157 /* FIXME: set error */
158 return NULL;
161 parser = g_new0 (ElfParser, 1);
163 parser->parser = bin_parser_new (data, length);
165 if (is_big_endian)
166 bin_parser_set_endian (parser->parser, BIN_BIG_ENDIAN);
167 else
168 bin_parser_set_endian (parser->parser, BIN_LITTLE_ENDIAN);
170 make_formats (parser, is_64);
173 /* Read ELF header */
175 bin_parser_set_offset (parser->parser, 0);
177 parser->n_sections = bin_parser_get_uint_field (
178 parser->parser, parser->header, "e_shnum");
179 section_names_idx = bin_parser_get_uint_field (
180 parser->parser, parser->header, "e_shstrndx");
181 section_headers = bin_parser_get_uint_field (
182 parser->parser, parser->header, "e_shoff");
184 /* Read section headers */
185 parser->sections = g_new0 (Section *, parser->n_sections);
187 bin_parser_set_offset (parser->parser, section_headers);
189 bin_parser_save (parser->parser);
191 bin_parser_seek_record (parser->parser, parser->shn_entry,
192 section_names_idx);
194 section_names = bin_parser_get_uint_field (
195 parser->parser, parser->shn_entry, "sh_offset");
197 bin_parser_restore (parser->parser);
199 for (i = 0; i < parser->n_sections; ++i)
201 parser->sections[i] = section_new (parser->parser,
202 parser->shn_entry,
203 section_names);
205 bin_parser_seek_record (parser->parser, parser->shn_entry, 1);
208 /* Cache the text section */
209 parser->text_section = find_section (parser, ".text", SHT_PROGBITS);
210 if (!parser->text_section)
211 parser->text_section = find_section (parser, ".text", SHT_NOBITS);
213 return parser;
216 ElfParser *
217 elf_parser_new (const char *filename,
218 GError **err)
220 const guchar *data;
221 gsize length;
222 ElfParser *parser;
224 GMappedFile *file = g_mapped_file_new (filename, FALSE, NULL);
226 if (!file)
227 return NULL;
229 #if 0
230 g_print ("elf parser new : %s\n", filename);
231 #endif
233 data = (guchar *)g_mapped_file_get_contents (file);
234 length = g_mapped_file_get_length (file);
236 #if 0
237 g_print ("data %p: for %s\n", data, filename);
238 #endif
240 parser = elf_parser_new_from_data (data, length);
242 if (!parser)
244 g_mapped_file_free (file);
245 return NULL;
248 parser->file = file;
250 #if 0
251 g_print ("Elf file: %s (debug: %s)\n",
252 filename, elf_parser_get_debug_link (parser, NULL));
253 #endif
255 parser->file = file;
257 #if 0
258 if (!parser->symbols)
259 g_print ("at this point %s has no symbols\n", filename);
260 #endif
262 return parser;
265 guint32
266 elf_parser_get_crc32 (ElfParser *parser)
268 static const unsigned long crc32_table[256] = {
269 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
270 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
271 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
272 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
273 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
274 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
275 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
276 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
277 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
278 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
279 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
280 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
281 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
282 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
283 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
284 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
285 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
286 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
287 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
288 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
289 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
290 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
291 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
292 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
293 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
294 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
295 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
296 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
297 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
298 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
299 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
300 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
301 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
302 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
303 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
304 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
305 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
306 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
307 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
308 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
309 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
310 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
311 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
313 const guchar *data;
314 gsize length;
315 gulong crc;
316 gsize i;
318 data = bin_parser_get_data (parser->parser);
319 length = bin_parser_get_length (parser->parser);
321 crc = 0xffffffff;
323 madvise ((char *)data, length, MADV_SEQUENTIAL);
325 for (i = 0; i < length; ++i)
326 crc = crc32_table[(crc ^ data[i]) & 0xff] ^ (crc >> 8);
328 /* We just read the entire file into memory, but we only really
329 * need the symbol table, so swap the whole thing out.
331 * We could be more exact here, but it's only a few minor
332 * pagefaults.
334 madvise ((char *)data, length, MADV_DONTNEED);
336 return ~crc & 0xffffffff;
339 void
340 elf_parser_free (ElfParser *parser)
342 int i;
344 for (i = 0; i < parser->n_sections; ++i)
345 section_free (parser->sections[i]);
346 g_free (parser->sections);
348 if (parser->file)
349 g_mapped_file_free (parser->file);
351 g_free (parser->symbols);
353 bin_parser_free (parser->parser);
355 g_free (parser);
358 extern char *sysprof_cplus_demangle (const char *name, int options);
360 char *
361 elf_demangle (const char *name)
363 #define DMGL_PARAMS (1 << 0) /* Include function args */
364 #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
366 char *demangled = sysprof_cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI);
368 if (demangled)
369 return demangled;
370 else
371 return g_strdup (name);
375 * Looking up symbols
377 static int
378 compare_sym (const void *a, const void *b)
380 const ElfSym *sym_a = a;
381 const ElfSym *sym_b = b;
383 if (sym_a->address < sym_b->address)
384 return -1;
385 else if (sym_a->address == sym_b->address)
386 return 0;
387 else
388 return 1;
391 #if 0
392 static void
393 dump_symbols (ElfParser *parser, ElfSym *syms, guint n_syms)
395 int i;
397 for (i = 0; i < n_syms; ++i)
399 ElfSym *s = &(syms[i]);
401 g_print (" %s: %lx\n", elf_parser_get_sym_name (parser, s), s->address);
404 #endif
406 static void
407 read_table (ElfParser *parser,
408 const Section *sym_table,
409 const Section *str_table)
411 int sym_size = bin_record_get_size (parser->sym_format);
412 int i;
413 int n_functions;
415 parser->n_symbols = sym_table->size / sym_size;
416 parser->symbols = g_new (ElfSym, parser->n_symbols);
418 #if 0
419 g_print ("sym table offset: %d\n", sym_table->offset);
420 #endif
422 bin_parser_set_offset (parser->parser, sym_table->offset);
424 n_functions = 0;
425 #if 0
426 g_print ("n syms: %d\n", parser->n_symbols);
427 #endif
428 for (i = 0; i < parser->n_symbols; ++i)
430 guint info;
431 gulong addr;
432 gulong offset;
434 info = bin_parser_get_uint_field (
435 parser->parser, parser->sym_format, "st_info");
436 addr = bin_parser_get_uint_field (
437 parser->parser, parser->sym_format, "st_value");
438 offset = bin_parser_get_offset (parser->parser);
440 if (addr != 0 &&
441 (info & 0xf) == STT_FUNC &&
442 ((info >> 4) == STB_GLOBAL ||
443 (info >> 4) == STB_LOCAL))
445 parser->symbols[n_functions].address = addr;
446 parser->symbols[n_functions].offset = offset;
448 n_functions++;
451 #if 0
452 g_print ("read symbol: %s\n", get_string_indirect (parser->parser,
453 parser->sym_format, "st_name",
454 str_table->offset));
455 #endif
458 bin_parser_seek_record (parser->parser, parser->sym_format, 1);
461 parser->sym_strings = str_table->offset;
462 parser->n_symbols = n_functions;
463 parser->symbols = g_renew (ElfSym, parser->symbols, parser->n_symbols);
465 qsort (parser->symbols, parser->n_symbols, sizeof (ElfSym), compare_sym);
468 static void
469 read_symbols (ElfParser *parser)
471 const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB);
472 const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB);
473 const Section *dynsym = find_section (parser, ".dynsym", SHT_DYNSYM);
474 const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB);
476 if (symtab && strtab)
478 read_table (parser, symtab, strtab);
480 else if (dynsym && dynstr)
482 read_table (parser, dynsym, dynstr);
484 else
486 /* To make sure parser->symbols is non-NULL */
487 parser->n_symbols = 0;
488 parser->symbols = g_new (ElfSym, 1);
492 static ElfSym *
493 do_lookup (ElfSym *symbols,
494 gulong address,
495 int first,
496 int last)
498 if (address >= symbols[last].address)
500 return &(symbols[last]);
502 else if (last - first < 3)
504 while (last >= first)
506 if (address >= symbols[last].address)
507 return &(symbols[last]);
509 last--;
512 return NULL;
514 else
516 int mid = (first + last) / 2;
518 if (symbols[mid].address > address)
519 return do_lookup (symbols, address, first, mid);
520 else
521 return do_lookup (symbols, address, mid, last);
525 /* Address should be given in 'offset into text segment' */
526 const ElfSym *
527 elf_parser_lookup_symbol (ElfParser *parser,
528 gulong address)
530 const ElfSym *result;
532 if (!parser->symbols)
534 #if 0
535 g_print ("reading symbols\n");
536 #endif
537 read_symbols (parser);
540 if (parser->n_symbols == 0)
541 return NULL;
543 if (!parser->text_section)
544 return NULL;
546 address += parser->text_section->load_address;
548 #if 0
549 g_print ("the address we are looking up is %p\n", address);
550 #endif
552 result = do_lookup (parser->symbols, address, 0, parser->n_symbols - 1);
554 #if 0
555 if (result)
557 g_print ("found %s at %lx\n", elf_parser_get_sym_name (parser, result), result->address);
559 #endif
561 if (result)
563 gulong size;
565 bin_parser_set_offset (parser->parser, result->offset);
567 size = bin_parser_get_uint_field (
568 parser->parser, parser->sym_format, "st_size");
570 if (result->address + size <= address)
571 result = NULL;
574 return result;
577 gulong
578 elf_parser_get_text_offset (ElfParser *parser)
580 g_return_val_if_fail (parser != NULL, (gulong)-1);
582 if (!parser->text_section)
583 return (gulong)-1;
585 return parser->text_section->offset;
588 const char *
589 elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
591 const Section *debug_link = find_section (parser, ".gnu_debuglink",
592 SHT_PROGBITS);
593 const gchar *result;
595 if (!debug_link)
596 return NULL;
598 bin_parser_set_offset (parser->parser, debug_link->offset);
600 result = bin_parser_get_string (parser->parser);
602 bin_parser_align (parser->parser, 4);
604 if (crc32)
605 *crc32 = bin_parser_get_uint (parser->parser, 4);
607 return result;
610 const guchar *
611 elf_parser_get_eh_frame (ElfParser *parser)
613 const Section *eh_frame = find_section (parser, ".eh_frame", SHT_PROGBITS);
615 if (eh_frame)
616 return bin_parser_get_data (parser->parser) + eh_frame->offset;
617 else
618 return NULL;
621 const char *
622 elf_parser_get_sym_name (ElfParser *parser,
623 const ElfSym *sym)
625 const char *result;
627 g_return_val_if_fail (parser != NULL, NULL);
629 bin_parser_set_offset (parser->parser, sym->offset);
630 result = get_string_indirect (
631 parser->parser, parser->sym_format, "st_name", parser->sym_strings);
633 return result;
636 gulong
637 elf_parser_get_sym_address (ElfParser *parser,
638 const ElfSym *sym)
640 return sym->address;
644 * Utility functions
646 static gboolean
647 parse_elf_signature (const guchar *data,
648 gsize length,
649 gboolean *is_64,
650 gboolean *is_be)
652 /* FIXME: this function should be able to return an error */
653 if (length < EI_NIDENT)
655 /* FIXME set error */
656 return FALSE;
659 if (data[EI_CLASS] != ELFCLASS32 &&
660 data[EI_CLASS] != ELFCLASS64)
662 /* FIXME set error */
663 return FALSE;
666 if (data[EI_DATA] != ELFDATA2LSB &&
667 data[EI_DATA] != ELFDATA2MSB)
669 /* FIXME set error */
670 return FALSE;
673 if (is_64)
674 *is_64 = (data[EI_CLASS] == ELFCLASS64);
676 if (is_be)
677 *is_be = (data[EI_DATA] == ELFDATA2MSB);
679 return TRUE;
682 static void
683 get_formats (gboolean is_64,
684 const BinField **elf_header,
685 const BinField **shn_entry,
686 const BinField **sym_format)
688 static const BinField elf64_header[] = {
689 { "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
690 { "e_type", BIN_UINT, 2 },
691 { "e_machine", BIN_UINT, 2 },
692 { "e_version", BIN_UINT, 4 },
693 { "e_entry", BIN_UINT, 8 },
694 { "e_phoff", BIN_UINT, 8 },
695 { "e_shoff", BIN_UINT, 8 },
696 { "e_flags", BIN_UINT, 4 },
697 { "e_ehsize", BIN_UINT, 2 },
698 { "e_phentsize", BIN_UINT, 2 },
699 { "e_phnum", BIN_UINT, 2 },
700 { "e_shentsize", BIN_UINT, 2 },
701 { "e_shnum", BIN_UINT, 2 },
702 { "e_shstrndx", BIN_UINT, 2 },
703 { "" },
706 static const BinField elf32_header[] = {
707 { "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
708 { "e_type", BIN_UINT, 2 },
709 { "e_machine", BIN_UINT, 2 },
710 { "e_version", BIN_UINT, 4 },
711 { "e_entry", BIN_UINT, 4 },
712 { "e_phoff", BIN_UINT, 4 },
713 { "e_shoff", BIN_UINT, 4 },
714 { "e_flags", BIN_UINT, 4 },
715 { "e_ehsize", BIN_UINT, 2 },
716 { "e_phentsize", BIN_UINT, 2 },
717 { "e_phnum", BIN_UINT, 2 },
718 { "e_shentsize", BIN_UINT, 2 },
719 { "e_shnum", BIN_UINT, 2 },
720 { "e_shstrndx", BIN_UINT, 2 },
721 { "" },
724 static const BinField shn64_entry[] = {
725 { "sh_name", BIN_UINT, 4 },
726 { "sh_type", BIN_UINT, 4 },
727 { "sh_flags", BIN_UINT, 8 },
728 { "sh_addr", BIN_UINT, 8 },
729 { "sh_offset", BIN_UINT, 8 },
730 { "sh_size", BIN_UINT, 8 },
731 { "sh_link", BIN_UINT, 4 },
732 { "sh_info", BIN_UINT, 4 },
733 { "sh_addralign", BIN_UINT, 8 },
734 { "sh_entsize", BIN_UINT, 8 },
735 { "" }
738 static const BinField shn32_entry[] = {
739 { "sh_name", BIN_UINT, 4 },
740 { "sh_type", BIN_UINT, 4 },
741 { "sh_flags", BIN_UINT, 4 },
742 { "sh_addr", BIN_UINT, 4 },
743 { "sh_offset", BIN_UINT, 4 },
744 { "sh_size", BIN_UINT, 4 },
745 { "sh_link", BIN_UINT, 4 },
746 { "sh_info", BIN_UINT, 4 },
747 { "sh_addralign", BIN_UINT, 4 },
748 { "sh_entsize", BIN_UINT, 4 },
749 { "" }
752 static const BinField sym64_format[] = {
753 { "st_name", BIN_UINT, 4 },
754 { "st_info", BIN_UINT, 1 },
755 { "st_other", BIN_UINT, 1 },
756 { "st_shndx", BIN_UINT, 2 },
757 { "st_value", BIN_UINT, 8 },
758 { "st_size", BIN_UINT, 8 },
759 { "" }
762 static const BinField sym32_format[] = {
763 { "st_name", BIN_UINT, 4 },
764 { "st_value", BIN_UINT, 4 },
765 { "st_size", BIN_UINT, 4 },
766 { "st_info", BIN_UINT, 1 },
767 { "st_other", BIN_UINT, 1 },
768 { "st_shndx", BIN_UINT, 2 },
769 { "" },
772 if (is_64)
774 *elf_header = elf64_header;
775 *shn_entry = shn64_entry;
776 *sym_format = sym64_format;
778 else
780 *elf_header = elf32_header;
781 *shn_entry = shn32_entry;
782 *sym_format = sym32_format;
786 static void
787 make_formats (ElfParser *parser, gboolean is_64)
789 const BinField *elf_header, *shn_entry, *sym_format;
791 get_formats (is_64, &elf_header, &shn_entry, &sym_format);
793 parser->header = bin_parser_create_record (parser->parser, elf_header);
794 parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry);
795 parser->sym_format = bin_parser_create_record (parser->parser, sym_format);