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.
22 #include "binparser.h"
23 #include "elfparser.h"
25 typedef struct Section Section;
48 BinRecord * strtab_format;
49 BinRecord * shn_entry;
50 BinRecord * sym_format;
51 BinRecord * note_format;
64 gboolean checked_build_id;
67 const Section * text_section;
70 static gboolean parse_elf_signature (const guchar *data, gsize length,
71 gboolean *is_64, gboolean *is_be);
72 static void make_formats (ElfParser *parser, gboolean is_64);
75 get_string_indirect (BinParser *parser,
80 const char *result = NULL;
83 bin_parser_save (parser);
85 index = bin_parser_get_uint_field (parser, record, name);
87 bin_parser_set_offset (parser, str_table + index);
89 result = bin_parser_get_string (parser);
91 bin_parser_restore (parser);
97 section_new (BinParser *parser,
101 Section *section = g_new (Section, 1);
104 section->name = get_string_indirect (parser, record, "sh_name", name_table);
105 section->size = bin_parser_get_uint_field (parser, record, "sh_size");
106 section->offset = bin_parser_get_uint_field (parser, record, "sh_offset");
108 flags = bin_parser_get_uint_field (parser, record, "sh_flags");
109 section->allocated = !!(flags & SHF_ALLOC);
111 if (section->allocated)
113 section->load_address = bin_parser_get_uint_field (
114 parser, record, "sh_addr");
118 section->load_address = 0;
121 section->type = bin_parser_get_uint_field (parser, record, "sh_type");
127 section_free (Section *section)
132 static const Section *
133 find_section (ElfParser *parser,
139 for (i = 0; i < parser->n_sections; ++i)
141 Section *section = parser->sections[i];
143 if (strcmp (section->name, name) == 0 && section->type == type)
151 elf_parser_new_from_data (const guchar *data,
155 gboolean is_64, is_big_endian;
156 int section_names_idx;
158 gsize section_headers;
161 if (!parse_elf_signature (data, length, &is_64, &is_big_endian))
163 /* FIXME: set error */
167 parser = g_new0 (ElfParser, 1);
170 g_print (" new parser : %p\n", parser);
173 parser->parser = bin_parser_new (data, length);
176 bin_parser_set_endian (parser->parser, BIN_BIG_ENDIAN);
178 bin_parser_set_endian (parser->parser, BIN_LITTLE_ENDIAN);
180 make_formats (parser, is_64);
183 /* Read ELF header */
185 bin_parser_set_offset (parser->parser, 0);
187 parser->n_sections = bin_parser_get_uint_field (
188 parser->parser, parser->header, "e_shnum");
189 section_names_idx = bin_parser_get_uint_field (
190 parser->parser, parser->header, "e_shstrndx");
191 section_headers = bin_parser_get_uint_field (
192 parser->parser, parser->header, "e_shoff");
194 /* Read section headers */
195 parser->sections = g_new0 (Section *, parser->n_sections);
197 bin_parser_set_offset (parser->parser, section_headers);
199 bin_parser_save (parser->parser);
201 bin_parser_seek_record (parser->parser, parser->shn_entry,
204 section_names = bin_parser_get_uint_field (
205 parser->parser, parser->shn_entry, "sh_offset");
207 bin_parser_restore (parser->parser);
209 for (i = 0; i < parser->n_sections; ++i)
211 parser->sections[i] = section_new (parser->parser,
215 bin_parser_seek_record (parser->parser, parser->shn_entry, 1);
218 /* Cache the text section */
219 parser->text_section = find_section (parser, ".text", SHT_PROGBITS);
220 if (!parser->text_section)
221 parser->text_section = find_section (parser, ".text", SHT_NOBITS);
223 parser->filename = NULL;
224 parser->build_id = NULL;
230 elf_parser_new (const char *filename,
237 GMappedFile *file = g_mapped_file_new (filename, FALSE, NULL);
243 g_print ("elf parser new : %s\n", filename);
246 data = (guchar *)g_mapped_file_get_contents (file);
247 length = g_mapped_file_get_length (file);
250 g_print ("data %p: for %s\n", data, filename);
253 parser = elf_parser_new_from_data (data, length);
256 g_print ("Parser for %s: %p\n", filename, parser);
261 g_mapped_file_free (file);
265 parser->filename = g_strdup (filename);
270 g_print ("Elf file: %s (debug: %s)\n",
271 filename, elf_parser_get_debug_link (parser, NULL));
273 if (!parser->symbols)
274 g_print ("at this point %s has no symbols\n", filename);
281 elf_parser_get_crc32 (ElfParser *parser)
283 static const unsigned long crc32_table[256] = {
284 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
285 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
286 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
287 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
288 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
289 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
290 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
291 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
292 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
293 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
294 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
295 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
296 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
297 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
298 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
299 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
300 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
301 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
302 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
303 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
304 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
305 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
306 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
307 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
308 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
309 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
310 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
311 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
312 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
313 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
314 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
315 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
316 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
317 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
318 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
319 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
320 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
321 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
322 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
323 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
324 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
325 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
326 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
333 data = bin_parser_get_data (parser->parser);
334 length = bin_parser_get_length (parser->parser);
338 madvise ((char *)data, length, MADV_SEQUENTIAL);
340 for (i = 0; i < length; ++i)
341 crc = crc32_table[(crc ^ data[i]) & 0xff] ^ (crc >> 8);
343 /* We just read the entire file into memory, but we only really
344 * need the symbol table, so swap the whole thing out.
346 * We could be more exact here, but it's only a few minor
350 madvise ((char *)data, length, MADV_DONTNEED);
352 return ~crc & 0xffffffff;
356 elf_parser_free (ElfParser *parser)
360 for (i = 0; i < parser->n_sections; ++i)
361 section_free (parser->sections[i]);
362 g_free (parser->sections);
365 g_mapped_file_free (parser->file);
367 g_free (parser->symbols);
369 bin_parser_free (parser->parser);
371 if (parser->filename)
372 g_free (parser->filename);
374 if (parser->build_id)
375 g_free (parser->build_id);
380 extern char *sysprof_cplus_demangle (const char *name, int options);
383 elf_demangle (const char *name)
385 #define DMGL_PARAMS (1 << 0) /* Include function args */
386 #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
388 char *demangled = sysprof_cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI);
393 return g_strdup (name);
400 compare_sym (const void *a, const void *b)
402 const ElfSym *sym_a = a;
403 const ElfSym *sym_b = b;
405 if (sym_a->address < sym_b->address)
407 else if (sym_a->address == sym_b->address)
415 dump_symbols (ElfParser *parser, ElfSym *syms, guint n_syms)
419 for (i = 0; i < n_syms; ++i)
421 ElfSym *s = &(syms[i]);
423 g_print (" %s: %lx\n", elf_parser_get_sym_name (parser, s), s->address);
429 read_table (ElfParser *parser,
430 const Section *sym_table,
431 const Section *str_table)
433 int sym_size = bin_record_get_size (parser->sym_format);
436 parser->n_symbols = sym_table->size / sym_size;
437 parser->symbols = g_new (ElfSym, parser->n_symbols);
440 g_print ("sym table offset: %d\n", sym_table->offset);
443 bin_parser_set_offset (parser->parser, sym_table->offset);
447 g_print ("n syms: %d\n", parser->n_symbols);
449 for (i = 0; i < parser->n_symbols; ++i)
456 info = bin_parser_get_uint_field (
457 parser->parser, parser->sym_format, "st_info");
458 addr = bin_parser_get_uint_field (
459 parser->parser, parser->sym_format, "st_value");
460 shndx = bin_parser_get_uint_field (
461 parser->parser, parser->sym_format, "st_shndx");
462 offset = bin_parser_get_offset (parser->parser);
465 g_print ("read symbol: %s (section: %d)\n", get_string_indirect (parser->parser,
466 parser->sym_format, "st_name",
472 shndx < parser->n_sections &&
473 parser->sections[shndx] == parser->text_section &&
474 (info & 0xf) == STT_FUNC &&
475 ((info >> 4) == STB_GLOBAL ||
476 (info >> 4) == STB_LOCAL ||
477 (info >> 4) == STB_WEAK)
480 parser->symbols[n_symbols].address = addr;
481 parser->symbols[n_symbols].offset = offset;
486 g_print (" symbol: %s: %lx\n",
487 get_string_indirect (parser->parser,
488 parser->sym_format, "st_name",
490 addr - parser->text_section->load_address);
491 g_print (" sym %d in %p (info: %d:%d) (func:global %d:%d)\n",
492 addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL);
498 g_print (" rejecting %d in %p (info: %d:%d) (func:global %d:%d)\n",
499 addr, parser, info & 0xf, info >> 4, STT_FUNC, STB_GLOBAL);
503 bin_parser_seek_record (parser->parser, parser->sym_format, 1);
506 parser->sym_strings = str_table->offset;
507 parser->n_symbols = n_symbols;
508 parser->symbols = g_renew (ElfSym, parser->symbols, parser->n_symbols);
510 qsort (parser->symbols, parser->n_symbols, sizeof (ElfSym), compare_sym);
514 read_symbols (ElfParser *parser)
516 const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB);
517 const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB);
518 const Section *dynsym = find_section (parser, ".dynsym", SHT_DYNSYM);
519 const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB);
521 if (symtab && strtab)
524 g_print ("reading symbol table of %s\n", parser->filename);
526 read_table (parser, symtab, strtab);
528 else if (dynsym && dynstr)
531 g_print ("reading dynamic symbol table of %s\n", parser->filename);
533 read_table (parser, dynsym, dynstr);
537 /* To make sure parser->symbols is non-NULL */
538 parser->n_symbols = 0;
539 parser->symbols = g_new (ElfSym, 1);
544 do_lookup (ElfSym *symbols,
549 if (address >= symbols[last].address)
551 return &(symbols[last]);
553 else if (last - first < 3)
555 while (last >= first)
557 if (address >= symbols[last].address)
558 return &(symbols[last]);
567 int mid = (first + last) / 2;
569 if (symbols[mid].address > address)
570 return do_lookup (symbols, address, first, mid);
572 return do_lookup (symbols, address, mid, last);
576 /* Address should be given in 'offset into text segment' */
578 elf_parser_lookup_symbol (ElfParser *parser,
581 const ElfSym *result;
583 if (!parser->symbols)
586 g_print ("reading symbols\n");
588 read_symbols (parser);
591 if (parser->n_symbols == 0)
594 if (!parser->text_section)
597 address += parser->text_section->load_address;
600 g_print ("elf: the address we are looking up is %p\n", address);
603 result = do_lookup (parser->symbols, address, 0, parser->n_symbols - 1);
608 g_print (" elf: found %s at %lx\n", elf_parser_get_sym_name (parser, result), result->address);
612 g_print ("elf: not found\n");
620 bin_parser_set_offset (parser->parser, result->offset);
622 size = bin_parser_get_uint_field (
623 parser->parser, parser->sym_format, "st_size");
625 if (size > 0 && result->address + size <= address)
628 g_print (" elf: ends at %lx, so rejecting\n",
629 result->address + size);
637 /* Reject the symbols if the address is outside the text section */
638 if (address > parser->text_section->load_address + parser->text_section->size)
646 elf_parser_get_text_offset (ElfParser *parser)
648 g_return_val_if_fail (parser != NULL, (gulong)-1);
650 if (!parser->text_section)
653 return parser->text_section->offset;
657 make_hex_string (const gchar *data, int n_bytes)
659 static const char hex_digits[] = {
660 '0', '1', '2', '3', '4', '5', '6', '7',
661 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
663 GString *string = g_string_new (NULL);
666 for (i = 0; i < n_bytes; ++i)
670 g_string_append_c (string, hex_digits[(c & 0xf0) >> 4]);
671 g_string_append_c (string, hex_digits[(c & 0x0f)]);
674 return g_string_free (string, FALSE);
678 elf_parser_get_build_id (ElfParser *parser)
680 if (!parser->checked_build_id)
682 const Section *build_id = find_section (parser, ".note.gnu.build-id", SHT_NOTE);
689 parser->checked_build_id = TRUE;
694 bin_parser_set_offset (parser->parser, build_id->offset);
696 name_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "name_size");
697 desc_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "desc_size");
698 type = bin_parser_get_uint_field (parser->parser, parser->note_format, "type");
700 bin_parser_seek_record (parser->parser, parser->note_format, 1);
701 name = bin_parser_get_string (parser->parser);
703 bin_parser_align (parser->parser, 4);
705 desc = bin_parser_get_string (parser->parser);
707 parser->build_id = make_hex_string (desc, desc_size);
710 return parser->build_id;
714 elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
716 const Section *debug_link = find_section (parser, ".gnu_debuglink",
723 bin_parser_set_offset (parser->parser, debug_link->offset);
725 result = bin_parser_get_string (parser->parser);
727 bin_parser_align (parser->parser, 4);
730 *crc32 = bin_parser_get_uint (parser->parser, 4);
736 get_section (ElfParser *parser,
739 const Section *section = find_section (parser, name, SHT_PROGBITS);
742 return bin_parser_get_data (parser->parser) + section->offset;
748 elf_parser_get_eh_frame (ElfParser *parser)
750 return get_section (parser, ".eh_frame");
754 elf_parser_get_debug_frame (ElfParser *parser)
756 return get_section (parser, ".debug_frame");
760 elf_parser_get_sym_name (ElfParser *parser,
765 g_return_val_if_fail (parser != NULL, NULL);
767 bin_parser_set_offset (parser->parser, sym->offset);
768 result = get_string_indirect (
769 parser->parser, parser->sym_format, "st_name", parser->sym_strings);
775 elf_parser_owns_symbol (ElfParser *parser,
778 ElfSym *first, *last;
780 if (!parser->n_symbols)
783 first = parser->symbols;
784 last = parser->symbols + parser->n_symbols - 1;
786 return first <= sym && sym <= last;
790 elf_parser_get_sym_address (ElfParser *parser,
793 return sym->address - parser->text_section->load_address;
800 parse_elf_signature (const guchar *data,
805 /* FIXME: this function should be able to return an error */
806 if (length < EI_NIDENT)
808 /* FIXME set error */
812 if (data[EI_CLASS] != ELFCLASS32 &&
813 data[EI_CLASS] != ELFCLASS64)
815 /* FIXME set error */
819 if (data[EI_DATA] != ELFDATA2LSB &&
820 data[EI_DATA] != ELFDATA2MSB)
822 /* FIXME set error */
827 *is_64 = (data[EI_CLASS] == ELFCLASS64);
830 *is_be = (data[EI_DATA] == ELFDATA2MSB);
836 get_formats (gboolean is_64,
837 const BinField **elf_header,
838 const BinField **shn_entry,
839 const BinField **sym_format,
840 const BinField **note_format_out)
842 static const BinField elf64_header[] = {
843 { "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
844 { "e_type", BIN_UINT, 2 },
845 { "e_machine", BIN_UINT, 2 },
846 { "e_version", BIN_UINT, 4 },
847 { "e_entry", BIN_UINT, 8 },
848 { "e_phoff", BIN_UINT, 8 },
849 { "e_shoff", BIN_UINT, 8 },
850 { "e_flags", BIN_UINT, 4 },
851 { "e_ehsize", BIN_UINT, 2 },
852 { "e_phentsize", BIN_UINT, 2 },
853 { "e_phnum", BIN_UINT, 2 },
854 { "e_shentsize", BIN_UINT, 2 },
855 { "e_shnum", BIN_UINT, 2 },
856 { "e_shstrndx", BIN_UINT, 2 },
860 static const BinField elf32_header[] = {
861 { "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
862 { "e_type", BIN_UINT, 2 },
863 { "e_machine", BIN_UINT, 2 },
864 { "e_version", BIN_UINT, 4 },
865 { "e_entry", BIN_UINT, 4 },
866 { "e_phoff", BIN_UINT, 4 },
867 { "e_shoff", BIN_UINT, 4 },
868 { "e_flags", BIN_UINT, 4 },
869 { "e_ehsize", BIN_UINT, 2 },
870 { "e_phentsize", BIN_UINT, 2 },
871 { "e_phnum", BIN_UINT, 2 },
872 { "e_shentsize", BIN_UINT, 2 },
873 { "e_shnum", BIN_UINT, 2 },
874 { "e_shstrndx", BIN_UINT, 2 },
878 static const BinField shn64_entry[] = {
879 { "sh_name", BIN_UINT, 4 },
880 { "sh_type", BIN_UINT, 4 },
881 { "sh_flags", BIN_UINT, 8 },
882 { "sh_addr", BIN_UINT, 8 },
883 { "sh_offset", BIN_UINT, 8 },
884 { "sh_size", BIN_UINT, 8 },
885 { "sh_link", BIN_UINT, 4 },
886 { "sh_info", BIN_UINT, 4 },
887 { "sh_addralign", BIN_UINT, 8 },
888 { "sh_entsize", BIN_UINT, 8 },
892 static const BinField shn32_entry[] = {
893 { "sh_name", BIN_UINT, 4 },
894 { "sh_type", BIN_UINT, 4 },
895 { "sh_flags", BIN_UINT, 4 },
896 { "sh_addr", BIN_UINT, 4 },
897 { "sh_offset", BIN_UINT, 4 },
898 { "sh_size", BIN_UINT, 4 },
899 { "sh_link", BIN_UINT, 4 },
900 { "sh_info", BIN_UINT, 4 },
901 { "sh_addralign", BIN_UINT, 4 },
902 { "sh_entsize", BIN_UINT, 4 },
906 static const BinField sym64_format[] = {
907 { "st_name", BIN_UINT, 4 },
908 { "st_info", BIN_UINT, 1 },
909 { "st_other", BIN_UINT, 1 },
910 { "st_shndx", BIN_UINT, 2 },
911 { "st_value", BIN_UINT, 8 },
912 { "st_size", BIN_UINT, 8 },
916 static const BinField sym32_format[] = {
917 { "st_name", BIN_UINT, 4 },
918 { "st_value", BIN_UINT, 4 },
919 { "st_size", BIN_UINT, 4 },
920 { "st_info", BIN_UINT, 1 },
921 { "st_other", BIN_UINT, 1 },
922 { "st_shndx", BIN_UINT, 2 },
926 static const BinField note_format[] = {
927 { "name_size", BIN_UINT, 4 },
928 { "desc_size", BIN_UINT, 4 },
929 { "type", BIN_UINT, 4 },
934 *elf_header = elf64_header;
935 *shn_entry = shn64_entry;
936 *sym_format = sym64_format;
940 *elf_header = elf32_header;
941 *shn_entry = shn32_entry;
942 *sym_format = sym32_format;
945 *note_format_out = note_format;
949 make_formats (ElfParser *parser, gboolean is_64)
951 const BinField *elf_header, *shn_entry, *sym_format, *note_format;
953 get_formats (is_64, &elf_header, &shn_entry, &sym_format, ¬e_format);
955 parser->header = bin_parser_create_record (parser->parser, elf_header);
956 parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry);
957 parser->sym_format = bin_parser_create_record (parser->parser, sym_format);
958 parser->note_format = bin_parser_create_record (parser->parser, note_format);