diff options
author | Elliott Hughes <enh@google.com> | 2015-02-24 19:24:25 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-02-24 19:24:25 +0000 |
commit | 36e62782f45c6b004d370a79fbc895e0f321181d (patch) | |
tree | a63e40b5dd9927bd04ec7427c8797975c2a71f85 /src/src | |
parent | b48bfdc826ebdd316d5d8a4ff8f213391f1c710b (diff) | |
parent | 03333823c75a1c1887e923828113a1b0fd12020c (diff) | |
download | android_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.tar.gz android_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.tar.bz2 android_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.zip |
Merge "Upgrade to elfutils 0.161."
Diffstat (limited to 'src/src')
41 files changed, 6586 insertions, 2868 deletions
diff --git a/src/src/ChangeLog b/src/src/ChangeLog index ff19b484..0ae863ed 100644 --- a/src/src/ChangeLog +++ b/src/src/ChangeLog @@ -1,3 +1,884 @@ +2014-12-18 Ulrich Drepper <drepper@gmail.com> + + * Makefile.am: Suppress output of textrel_check command. + +2014-12-17 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_cfa_program): Add bounds check before each op that + takes at least one argument. + +2014-12-16 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_decoded_line_section): Print dwarf_errmsg if + dwarf_onesrcline or dwarf_linesrc fails. + +2014-12-16 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_line_section): Correct overflow check for + unit_length. + (print_debug_aranges_section): Correct overflow check for length. + +2014-12-15 Mark Wielaard <mjw@redhat.com> + + * readelf.c (notice_listptr): Return false if offset doesn't fit + in 61-bits. + (attr_callback): Warn if loclist or rangelist offset doesn't fit. + +2014-12-15 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Don't assert when addr_size or ref_size + is not 4 or 8, just report invalid data. + +2014-12-15 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Add more bounds checks. + +2014-12-15 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_line_section): Check there is enough room + for DW_LNE_set_address argument. Make sure there is enough room + for the the initial unit_length. + +2014-12-14 Mark Wielaard <mjw@redhat.com> + + * elflint.c (check_attributes): Call get_uleb128 with end pointer. + * readelf.c (print_attributes): Likewise. + (print_ops): Likewise and also for get_sleb128. + (print_cfa_program): Likewise and add more readp bounds checks. + (read_encoded): Likewise. + (print_debug_frame_section): Likewise. + (print_debug_line_section): Likewise. + (print_debug_macinfo_section): Likewise. + (print_debug_macro_section): Likewise. + (print_debug_exception_table): Likewise. + +2014-12-16 Mark Wielaard <mjw@redhat.com> + + * elfcmp.c (compare_Elf32_Word): Make sure (unsigned) Elf32_Word + difference doesn't wrap around before returning as int. + +2014-12-11 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_exception_table): Check TType base offset + and Action table are sane. + +2014-12-11 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_frame_section): Check number of augmentation + chars to print. + +2014-12-09 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_file_note): Check count fits data section and + doesn't overflow fptr. + +2014-12-08 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_exception_table): Report invalid data if + action table doesn't immediately follow call site table. + +2014-12-10 Josh Stone <jistone@redhat.com> + + * addr2line.c (get_diename): New, get linkage_name or name. + * addr2line.c (print_dwarf_function): Use get_diename. + * addr2line.c (handle_address): Likewise. + * addr2line.c (print_diesym): Removed. + +2014-12-10 Josh Stone <jistone@redhat.com> + + * addr2line.c (handle_address): Find the proper inline parents. + +2014-12-07 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_line_section): max_ops_per_instr cannot + be zero. + +2014-12-07 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Handle zero ref_size for DW_OP_call_ref + and DW_OP_GNU_implicit_pointer. + +2014-12-04 Mark Wielaard <mjw@redhat.com> + + * objdump.c (show_relocs_x): Make sure destshdr exists. + (show_relocs_rel): Don't rely on shdr->sh_entsize, use gelf_fsize. + (show_relocs_rela): Likewise. + (show_relocs): Make sure destshdr, symshdr and symdata exists. + +2014-11-30 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_sysv_hash64): Fix overflow check. + +2014-11-28 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_relocs_rel): Don't reuse destshdr to store + section header of a relocation against a STT_SECTION symbol. Use + a new local variable secshdr. + (handle_relocs_rela): Likewise. + +2014-11-26 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_aranges_section): Cast Dwarf_Word length + to ptrdiff_t for comparison. + +2014-11-24 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_line_section): Check line_range is not zero + before usage. + +2014-11-23 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_aranges_section): Check length to catch + nexthdr overflow. + +2014-11-21 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_attributes): Guard against empty section. + Document attribute format. Break when vendor name isn't terminated. + Add overflow check for subsection_len. Handle both gnu and non-gnu + attribute tags. + +2014-11-22 Mark Wielaard <mjw@redhat.com> + + * elflint.c (check_sections): Call ebl_bss_plt_p without ehdr. + * findtextrel.c (process_file): Use elf_getphdrnum. + * readelf.c (process_elf_file): Remove redundant ehdr->e_phoff check. + (print_phdr): Check phnum. + * size.c (show_segments): Use elf_getphdrnum. + * strip.c (handle_elf): Likewise. + * unstrip.c (copy_elf): Likewise. + (copy_elided_sections): Likewise. + (handle_file): Likewise. + +2014-11-18 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_cfa_program): Fix sanity check of DW_FORM_block + length. + +2014-11-17 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_verneed): Check vna_next and vn_next exist. + (handle_verdef): Check vda_next and vd_next exist. + (handle_versym): Check vd_next, vna_next and vn_next exist. + Check vername and filename are not NULL before use. + +2014-11-17 Mark Wielaard <mjw@redhat.com> + + * elfcmp.c (main): Check section names are NULL before use. + * objdump.c (section_match): Likewise. + * size.c (show_sysv): Likewise. + +2014-11-17 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_frame_section): Warn if ptr_size is not 4 + or 8 instead of just calling print_cfa_program. + +2014-11-16 Mark Wielaard <mjw@redhat.com> + + * readelf (process_elf_file): Set phnum to zero if there aren't + actually any pheaders. + (print_phdr): Check there actually is a phdr. + +2014-11-16 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_cfa_program): Check block len before calling + print_ops. + +2014-11-14 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_frame_section): Sanity Check CIE + unit_length and augmentationlen. + +2014-11-14 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_versym): Check def == NULL before use. + +2014-11-08 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_versym): Initialize vername and filename array + elements. + +2014-11-07 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_sysv_hash): Sanity check section contents. + (handle_sysv_hash64): Likewise. + (handle_gnu_hash): Likewise. + +2014-09-14 Petr Machata <pmachata@redhat.com> + + * readelf.c (handle_relocs_rela): Typo fix, test DESTSHDR properly. + +2014-09-12 Petr Machata <pmachata@redhat.com> + + * readelf.c (encoded_ptr_size): In the switch statement, change + magic constants 3 and 4 to DW_EH_PE_* counterparts. Still accept + 0. Print diagnostic for anything else. + +2014-08-25 Josh Stone <jistone@redhat.com> + + * Makefile.am: Prevent premature @AR@ replacement in a sed expression. + +2014-07-04 Menanteau Guy <menantea@linux.vnet.ibm.com> + Mark Wielaard <mjw@redhat.com> + + * elflint (check_symtab): Add ".TOC." to the list of possibly + dangling symbols because of sourceware PR13621. + +2014-06-14 Mark Wielaard <mjw@redhat.com> + + * elflint (check_symtab): Use ebl_func_addr_mask on st_value. + +2014-05-27 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug): Skip section if name is NULL. + +2014-05-26 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_relocs_rela): Print header like handle_relocs_rel + does, when sh_info == 0. + +2014-05-26 Mark Wielaard <mjw@redhat.com> + + * unstrip.c (find_alloc_sections_prelink): Allow non-split .bss + section when sh_size of the original and undo .bss section are equal. + +2014-05-26 Mark Wielaard <mjw@redhat.com> + + * unstrip.c (options): Add --force, -F. + (struct arg_info): Add bool force. + (parse_opt): Handle 'F', set force. + (handle_explicit_files): Add force argument, add warn function, + separate check ehdr field checks, use warn. + (handle_dwfl_module): Add force argument, pass on to + handle_explicit_files. + (handle_output_dir_module): Add force argument, pass on to + handle_dwfl_module. + (handle_implicit_modules): Pass info->force to handle_dwfl_module and + handle_output_dir_module. + (main): Pass info.force to handle_explicit_files. + +2014-05-19 Mark Wielaard <mjw@redhat.com> + + * elflint.c (check_reloc_shdr): Check ebl_check_reloc_target_type. + +2014-05-01 Mark Wielaard <mjw@redhat.com> + + * readelf.c (find_no_debuginfo): Call dwfl_standard_find_debuginfo + if looking for alternate debug file. + +2014-04-11 Mark Wielaard <mjw@redhat.com> + + * Makefile.am (AM_CPPFLAGS): Add -I libdwelf. + +2014-04-22 Mark Wielaard <mjw@redhat.com> + + * readelf.c (handle_core_item): Make sure variable length array + contains at least enough space for terminating zero char. + +2014-04-22 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Use unsigned int for 31 bits + left shift. + +2014-03-13 Mark Wielaard <mjw@redhat.com> + + * Makefile.am: Remove no_mudflap.os. Remove libmudflap from all + LDADD lines. + * strings.c (process_chunk): Remove _MUDFLAP condition. + +2014-04-09 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_aranges_section): Don't get the raw section + data, use the possibly decompressed .[z]debug sectiondata. + (print_debug_ranges_section): Likewise. + (print_debug_frame_section): Likewise. + (print_debug_line_section): Likewise. + (print_debug_loc_section): Likewise. + (print_debug_macinfo_section): Likewise. + (print_debug_macro_section): Likewise. + +2014-04-10 Mark Wielaard <mjw@redhat.com> + + * readelf.c (buf_read_ulong): Pass actual long size to convert. + +2014-03-05 Mark Wielaard <mjw@redhat.com> + + * readelf.c (attr_callback): Print DW_FORM_sdata values as signed + numbers. + +2014-02-24 Mark Wielaard <mjw@redhat.com> + + * readelf (print_phdr): Check there is a SHT_PROGBITS section at the + offset given by p_offsets for a PT_INTERP segment before trying to + display the interpreter string. + +2014-02-07 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_phdr): Check phdr->p_filesz and make sure + interpreter string is zero terminated before calling printf. + +2014-01-22 Mark Wielaard <mjw@redhat.com> + + * Makefile.am (nm_no_Wformat): Removed. + (size_no_Wformat): Likewise. + (strings_no_Wformat): Likewise. + (addr2line_no_Wformat): Likewise. + * size.c (show_sysv): Use fmtstr directly as literal in printf. + (show_sysv_one_line): Likewise. + * strings.c (locfmt): Removed. + (radix): New static enum. + (parse_opt): Set radix, not locfmt. + (process_chunk_mb): Use fmtstr directly as literal in printf based + on radix. + (process_chunk): Likewise. + * nm.c (show_symbols_sysv): Use fmtstr directly as literal in printf. + (show_symbols_bsd): Likewise. + (show_symbols_posix): Likewise. + +2014-01-21 Mark Wielaard <mjw@redhat.com> + + * stack.c (show_inlines): New static boolean. + (print_frame): New function split out from... + (print_frames): ..here. If show_inlines is true and we found a + DIE for the frame address, call print_inline_frames otherwise + call print_frame. Keep track of and track frame_nr. + (print_inline_frames): New function. + (parse_opt): Handle '-i'. + (main): Add 'i' to options. + +2014-01-27 Mark Wielaard <mjw@redhat.com> + + * stack.c (maxframes): Initialize to 256. + (main): Document new default in options. Document magic number + used in frames.allocated initialization. + +2014-01-20 Mark Wielaard <mjw@redhat.com> + + * stack.c (show_debugname): New static boolean. + (die_name): New function. + (print_frames): If show_debugname is true set symname to the + first function-like DIE with a name in scope for the address in + the debuginfo. + (parse_opt): Handle '-d'. + (main): Add 'd' to options. + +2014-01-20 Mark Wielaard <mjw@redhat.com> + + * addr2line.c (handle_address): Initialize scopes to NULL. + +2014-01-17 Roland McGrath <roland@redhat.com> + + * strip.c (handle_elf): Check for bogus values in sh_link, sh_info, + st_shndx, e_shstrndx, and SHT_GROUP or SHT_SYMTAB_SHNDX data. + Don't use assert on input values, instead bail with "illformed" error. + +2014-01-17 Roland McGrath <roland@redhat.com> + + * readelf.c (handle_dynamic, handle_symtab): Check for bogus sh_link. + (handle_verneed, handle_verdef, handle_versym, handle_hash): Likewise. + (handle_scngrp): Check for bogus sh_info. + +2014-01-17 Jakub Jelinek <jakub@redhat.com> + + * elflint.c (section_name): Return "<invalid>" instead of + crashing on invalid section name. + (check_symtab, is_rel_dyn, check_rela, check_rel, check_dynamic, + check_symtab_shndx, check_hash, check_versym): Robustify. + (check_hash): Don't check entries beyond end of section. + (check_note): Don't crash if gelf_rawchunk fails. + +2014-01-17 Petr Machata <pmachata@redhat.com> + + * readelf.c (handle_dynamic, handle_relocs_rel) + (handle_relocs_rela, handle_versym, print_liblist): + Use gelf_fsize instead of relying on shdr->sh_entsize. + +2014-01-14 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_macro_section): Clear vendor array before + use. + +2014-01-15 Jan Kratochvil <jan.kratochvil@redhat.com> + + Fix corruption of non-C++ symbols by the demangler. + * nm.c (show_symbols_sysv, show_symbols_bsd, show_symbols_posix) + (show_symbols): Check for _Z. + * stack.c (print_frames) <USE_DEMANGLE>: Check for _Z. + +2014-01-02 Mark Wielaard <mjw@redhat.com> + + * stack.c (show_raw): Declare unconditionally. + (parse_opt): Handle '-r' unconditionally. + (main): Show "raw" option even without USE_DEMANGLE. + +2014-01-02 Mark Wielaard <mjw@redhat.com> + + * stack.c (print_frames): Print 0x before build-id hex-offset. + +2014-01-02 Mark Wielaard <mjw@redhat.com> + + * stack.c (maxframes): Increase to 2048. + (struct frames): Add allocated field. + (frame_callback): If frames used is frames allocated, realloc. + (print_frames): Show an error if maxframes has been reached. + (parse_opt): Allow -n 0 for unlimited frames. + (main): Document -n 0 and new default 2048 frames. Allocate initial + number of frames with malloc. + +2013-12-30 Mark Wielaard <mjw@redhat.com> + + * stack.c (parse_opt): Explicitly call dwfl_linux_proc_attach + or dwfl_core_file_attach and check for errors. + +2013-12-28 Mark Wielaard <mjw@redhat.com> + + * stack.c (print_frames): Remove address width code and use... + (get_addr_width): ...this new function. + (show_modules): New static boolean. + (module_callback): New static function. + (parse_opt): Handle '-l'. + (main): Add 'l' to options. If show_modules then use dwfl_getmodules + with module_callback to show all detected modules and possible + build_id, elf and dwarf files. + +2013-12-27 Mark Wielaard <mjw@redhat.com> + + * stack.c (frames_shown): New static boolean. + (EXIT_OK,EXIT_ERROR,EXIT_BAD,EXIT_USAGES): New defines. + (frame_callback): Return -1 on error. Don't print error. + (print_frames): Add arguments, tid, dwflerr and what. Print tid. + If there was an error report it with address and module if possible. + Record whether any frames were actually printed. + (thread_callback): Collect tid and err, pass it to print_frames. + (parse_opt): Use EXIT_BAD for errors. On ARGP_KEY_END print errno + if dwfl_linux_proc_report returned it. Check whether we are properly + attached with dwfl_pid. + (main): Document exit status. Don't report DWARF_CB_ABORT from + callbacks as error. Pass real errors to print_frames. Return + EXIT_BAD if no frames could be shown. Return EXIT_ERROR if there + were any non-fatal errors. + +2013-12-23 Mark Wielaard <mjw@redhat.com> + + * Makefile.am (stack_LDADD): Add demanglelib. + * stack.c (show_quiet): New static boolean, default false. + (show_raw): Likewise. + (demangle_buffer_len): New static size_t. + (demangle_buffer): New static char *. + (print_frames): Don't resolve pc name if show_quiet. Demangle name + unless show_raw. + (parse_opt): Handle '-q' and '-r'. + (main): Add 'q' and 'r' to options. Free demangle_buffer. + +2013-12-23 Mark Wielaard <mjw@redhat.com> + + * stack.c (OPT_DEBUGINFO): New define. + (OPT_COREFILE): Likewise. + (pid): New static. + (core_fd): Likewise. + (core): Likewise. + (exec): Likewise. + (debuginfo_path): Likewise. + (parse_opt): Handle '-p', '--core', '-e' and '--debuginfo-path'. + Do argument sanity checking. Setup Dwfl. + (main): Add 'p', 'core', 'e' and 'debuginfo-path' to options. + Remove argp_child children, simplify argp doc, remove custom + usage message and construction of dwfl with dwfl_standard_argp. + Use pid directly as tid. close core and core_fd if opened. Print + pid of process or core. + +2013-12-23 Mark Wielaard <mjw@redhat.com> + + * stack.c (show_build_id): New static boolean. + (print_frames): Print module build-id, load address and pc offset + if show_build_id is true. + (parse_opt): Handle '-b'. + (main): Add -b to options. + +2013-12-22 Mark Wielaard <mjw@redhat.com> + + * stack.c (maxframes): New static unsigned. Initialize to 64. + (struct frame): New struct. + (struct frames): Likewise. + (dwfl): New static Dwfl pointer. + (frame_callback): Use arg as struct frames and fill it next frame. + Return DWARF_CB_ABORT when maxframes has been reached. Move + printing of frame to... + (print_frames): ...here. New function. + (thread_callback): Use arg as struct frames and set frames to zero. + Call print_frames. + (parse_opt): Handle '-n'. + (main): Add -n to options. Allocate frames using maxframes. Pass + frames to frame_callback and thread_callback. + +2013-12-20 Mark Wielaard <mjw@redhat.com> + + * stack.c (show_one_tid): New static boolean. + (parse_opt): Handle '-1'. + (main): Add -1 to options. Call dwfl_getthread_frames when + show_one_tid is true. + +2013-12-18 Mark Wielaard <mjw@redhat.com> + + * addr2line.c (options): Add symbol-sections, 'x'. + (show_symbol_sections): New static bool. + (parse_opt): Handle 'x'. + (print_addrsym): Use dwfl_module_addrinfo value.r + Also show section of address with show_symbol_sections. + (find_symbol): Use dwfl_module_getsym_info and set value. + (handle_address): Request value and use it instead of sym.st_value. + * readelf.c (format_dwarf_addr): Use dwfl_module_addrinfo to get + name and offset. + +2013-12-17 Masatake YAMATO <yamato@redhat.com> + Mark Wielaard <mjw@redhat.com> + + * stack.c (show_activation, show_module, show_source): New variables. + (parse_opt): Set show_activation if -a option is given. + Set show_module if -m option is given. Set show_source if -s option + is given. Set all show booleans when -v option is given. + (main): Added `-a', `-m', `-s', and `-v' to the help message. + (frame_callback): Print module and source file information. + +2013-11-25 Petr Machata <pmachata@redhat.com> + + * elflint.c (valid_e_machine): Add EM_AARCH64. + +2013-11-14 Petr Machata <pmachata@redhat.com> + + * readelf.c (handle_core_item) <'h'>: New branch for handling + fields that shouldn't be displayed. + +2013-11-10 Mark Wielaard <mjw@redhat.com> + + * stack.c: Use ARGP_PROGRAM_VERSION_HOOK_DEF and + ARGP_PROGRAM_BUG_ADDRESS_DEF. + (print_version): New function. + +2013-11-09 Mark Wielaard <mjw@redhat.com> + + * arlib.c (arlib_init): Call snprintf before using the result + with memcpy. + (arlib_finalize): Likewise. + * nm.c (show_symbols_sysv): Don't modify cnt inside assert. + +2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> + + * Makefile.am (bin_PROGRAMS): Add stack. + (stack_LDADD): New. + * stack.c: New file. + +2013-11-05 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_ranges_section): Cast address to size_t + before comparison. + (print_debug_loc_section): Likewise. + +2013-10-18 Mark Wielaard <mjw@redhat.com> + + * ar.c (main): Correct operation check when instance_specifed is set. + +2013-09-26 Petr Machata <pmachata@redhat.com> + + * readelf.c (handle_file_note): New function. + (handle_notes_data): Call it to handle NT_FILE notes. + +2013-09-26 Petr Machata <pmachata@redhat.com> + + * readelf.c (handle_siginfo_note): New function. + (handle_notes_data): Call it to handle NT_SIGINFO notes. + (buf_read_int, buf_read_ulong, buf_has_data): New functions. + +2013-08-13 Mark Wielaard <mjw@redhat.com> + + * addr2line.c (options): Add "inlines", 'i'. + (show_inlines): New bool. + (parse_opt): Handle 'i'. + (print_diesym): New static function. + (print_src): New function taking code from... + (handle_address): here. Call print_src. Print inlines. + +2013-08-12 Mark Wielaard <mjw@redhat.com> + + * addr2line.c (main): If there is a newline char at end of buf, + then remove it. + +2013-07-05 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Take CU as argument, use it to print + parameter_ref DIE offset. + (struct listptr): Replace base field with cu. + (listptr_base): New function. + (compare_listptr): Use listptr_base. + (notice_listptr): Take CU as argument. + (skip_listptr_hole): Likewise. + (print_debug_ranges_section): Pass NULL as CU to skip_listptr_hole. + (print_cfa_program): Pass NULL as CU to print_ops. + (struct attrcb_args): Replace cu_base field with cu. + (attr_callback): Pass cu not cu_base to notice_listptr. + (print_debug_units): Don't calculate base, just set cu. + (print_debug_loc_section): Pass cu to skip_listptr_hole and + print_ops. + +2013-05-06 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Format first DW_OP_GNU_implicit_pointer + argument as DIE offset. + +2013-04-24 Mark Wielaard <mjw@redhat.com> + + * Makefile.am: Use AM_CPPFLAGS instead of INCLUDES. + +2013-03-25 Mark Wielaard <mjw@redhat.com> + + * readelf.c (argp_options): Add decodedline. + (decodedline): New boolean initialized to false. + (parse_opt): Set decodedline when arg is decodedline. + (print_decoded_line_section): New function. + (print_debug_line_section): Call print_decoded_line_section when + decodedline is true. + +2013-03-25 Mark Wielaard <mjw@redhat.com> + + * readelf.c (argp_option): Add decodedaranges. + (decodedaranges): New boolean initialized to false. + (parse_opt): Set decodedaranges when arg is decodedaranges. + (print_debug_aranges_section): Reimplemented and original + implementation renamed to... + (print_decoded_aranges_section): this. + +2013-03-25 Mark Wielaard <mjw@redhat.com> + + * readelf.c (attrcb_args): Add Dwarf_Die. + (attr_callback): When highpc is in constant form also print as + address. + (print_debug_units): Set args.die. + +2013-03-19 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Free format_dwarf_addr results. + +2013-03-18 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Accept version 8. + +2013-03-01 Mark Wielaard <mjw@redhat.com> + + * findtextrel.c (process_file): Release ELF and close file when not + text relocations are found. + * strip.c (handle_elf): Track memory used for .debuglink section data + and free when done. + +2013-02-24 Mark Wielaard <mjw@redhat.com> + + * elflint.c (check_symtab): Add __bss_start__ to the list of symbols + allowed to have out of section values because of GNU ld bugs. + +2013-02-06 Mark Wielaard <mjw@redhat.com> + + * elflint.c (check_symtab): Add __bss_start and __TMC_END__ to the + list of symbols allowed to have out of section values because of + GNU ld bugs in either .symtab or .dynsym, but only when they are + zero sized. + +2013-01-24 Mark Wielaard <mjw@redhat.com> + + * readelf.c (argp_option): Add unresolved-address-offsets, U. + (print_unresolved_addresses): New static. + (parse_opt): Handle 'U', set print_unprocessed_values. + (format_dwarf_addr): Take and handle new raw argument. + (print_ops): Call format_dwarf_addr with raw offset values. + (print_debug_ranges_section): Likewise. + (print_debug_frame_section): Likewise. + (attr_callback): Likewise. + (print_debug_line_section): Likewise. + (print_debug_loc_section): Likewise. + (print_gdb_index_section): Likewise. + +2013-01-18 Mark Wielaard <mjw@redhat.com> + + * readelf.c (struct listptr): Add base Dwarf_Addr field. + (compare_listptr): Warn for same offset with different base. + (notice_listptr): Take base argument and set it. + (skip_listptr_hole): Likewise. + (struct attrcb_args): Removed unused cu_offset field. + Add cu_base Dwarf_Addr field. + (attr_callback): Call notice_listptr with cbargs->cu_base. + (print_debug_units): Set args.cu_base. + (print_debug_ranges_section): Get base and use for format_dwarf_addr. + (print_debug_loc_section): Likewise. + +2013-01-29 Jan Kratochvil <jan.kratochvil@redhat.com> + + * readelf.c (handle_core_items): Limit special repeated items handling + to single-item formats '\n', 'b' and 'B', assert OFFSET 0 there. + +2012-12-18 Mark Wielaard <mark@bordewijk.wildebeest.org> + + * readelf.c (ELF_INPUT_SECTION): New argp key value. + (argp_option): Add elf-section. + (elf_input_section): New static. + (parse_opt): Handle ELF_INPUT_SECTION and set elf_input_section. + (open_input_section): New function. + (process_file): Call open_input_section if elf_input_section set. + +2013-01-13 David Abdurachmanov <David.Abdurachmanov@cern.ch> + + ar.c (do_oper_delete): Fix num passed to memset. + +2012-12-21 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_frame_section): Adjust FDE start address + if pcrel before feeding it to format_dwarf_addr. + +2012-12-21 Mark Wielaard <mjw@redhat.com> + + * addr2line.c (main): Call dwfl_end. + +2012-12-11 Roland McGrath <roland@hack.frob.com> + + * nm.c (show_symbols_sysv): Fix size passed to snprintf for invalid + sh_name case. + Reported by David Abdurachmanov <David.Abdurachmanov@cern.ch>. + +2012-10-16 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): DW_OP_skip and DW_OP_bra targets are + calculated beginning after the operand and 2-byte constant. + +2012-10-12 Jan Kratochvil <jan.kratochvil@redhat.com> + + * readelf.c (ITEM_WRAP_COLUMN, REGISTER_WRAP_COLUMN): Merge to ... + (WRAP_COLUMN): ... here. + (print_core_item): Remove parameter format_max. Update function + comment. Replace FORMAT_MAX by the real output width. + (handle_core_item): Remove the FORMAT_MAX values in TYPES, DO_TYPE, + calls of print_core_item, remove variable maxfmt, change + ITEM_WRAP_COLUMN to WRAP_COLUMN. + (handle_core_register): Remove the FORMAT_MAX values in TYPES, BITS, + calls of print_core_item, change REGISTER_WRAP_COLUMN to WRAP_COLUMN. + +2012-10-11 Jan Kratochvil <jan.kratochvil@redhat.com> + + * readelf.c (handle_core_item) <b>: Make run an outer block variable. + Increase run only if LASTBIT != 0. Print last element only if RUN > 0. + +2012-08-27 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_macro_section): Print offset as PRIx64. + +2012-08-27 Mark Wielaard <mjw@redhat.com> + + * readelf.c (register_info): Handle loc == NULL. + +2012-08-22 Jeff Kenton <jkenton@tilera.com> + + * elflint.c (valid_e_machine): Add EM_TILEGX and EM_TILEPRO. + +2012-08-16 Mark Wielaard <mjw@redhat.com> + + * readelf.c (dwarf_tag_name): Renamed from dwarf_tag_string. + Uses new dwarf_tag_string or adds ??? or lo_user+%#x when + appropriate. + (dwarf_attr_name): Likewise. + (dwarf_form_name): Likewise. + (dwarf_lang_name): Likewise. + (dwarf_inline_name): Likewise. + (dwarf_encoding_name): Likewise. + (dwarf_access_name): Likewise. + (dwarf_visibility_name): Likewise. + (dwarf_virtuality_name): Likewise. + (dwarf_identifier_case_name): Likewise. + (dwarf_calling_convention_name): Likewise. + (dwarf_ordering_name): Likewise. + (dwarf_discr_list_name): Likewise. + (print_ops): Remove KNOWN. Use dwarf_locexpr_opcode_string. + (attr_callback): Call new dwarf_foobar_name instead of old + dwarf_foobar_string functions. + (dwarf_tag_string): New function using known-dwarf.h macros. + (dwarf_attr_string): Likewise. + (dwarf_form_string): Likewise. + (dwarf_lang_string): Likewise. + (dwarf_inline_string): Likewise. + (dwarf_encoding_string): Likewise. + (dwarf_access_string): Likewise. + (dwarf_visibility_string): Likewise. + (dwarf_virtuality_string): Likewise. + (dwarf_identifier_case_string): Likewise. + (dwarf_calling_convention_string): Likewise. + (dwarf_ordering_string): Likewise. + (dwarf_discr_list_string): Likewise. + (dwarf_locexpr_opcode_string): Likewise. + +2012-06-27 Mark Wielaard <mjw@redhat.com> + + * readelf.c (dwarf_form_string): Handle DW_FORM_GNU_ref_alt and + DW_FORM_GNU_strp_alt. + (attr_callback): Likewise. + +2012-07-30 Petr Machata <pmachata@redhat.com> + + * nm.c (show_symbols_bsd): Reorder arguments in {S,}FMTSTRS (and + corresponding printf) so that those that are referenced by only + one of the formatting strings are at the end. + +2012-07-29 Mark Wielaard <mjw@redhat.com> + + * readelf.c (dwarf_lang_string): Use DW_LANG_ObjC, not DW_LANG_Objc. + (print_ops): Use known[op], not op_name, for DW_OP_GNU_parameter_ref. + +2012-07-19 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Handle DW_OP_GNU_parameter_ref. + +2012-07-11 Mark Wielaard <mjw@redhat.com> + + * readelf.c (options): Add macro to help of debug-dump. + (section_e): Add section_macro. + (section_all): Add section_macro. + (parse_opt): Handle macro. + (print_debug_macro_section): New function. + (print_debug): Add NEW_SECTION (macro). + +2012-07-10 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Add version 7 support. + Keep track of cu_nr. Print kind and static/global flag for each + symbol. When a symbol is in the TU list add 'T'. + +2012-06-26 Mark Wielaard <mjw@redhat.com> + + * readelf.c (dwarf_attr_string): Add DW_AT_GNU_macros. + +2012-06-22 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Cast printf PRIu/x64 arguments to uint64_t + for gcc 4.7 -Wformat. + +2012-05-09 Roland McGrath <roland@hack.frob.com> + + * elflint (check_sections): Allow zero sized sections at (filesz) end + of segment. And make check overflow-proofed. + +2012-04-24 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_ops): Add DW_OP_GNU_push_tls_address, + DW_OP_GNU_uinit and DW_OP_GNU_encoded_addr. + +2012-03-28 Roland McGrath <roland@hack.frob.com> + + * elflint.c (special_sections): Accept SHF_INFO_LINK for reloc sections. + +2012-03-28 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_debug_abbrev_section): Check there is Dwarf + section data. + (print_debug_str_section): Likewise. + +2012-03-21 Mark Wielaard <mjw@redhat.com> + + * readelf.c (print_gdb_index_section): Accept version 6. + 2012-01-31 Mark Wielaard <mjw@redhat.com> * readelf.c (attr_callback): Don't special case DW_FORM_sec_offset. diff --git a/src/src/Makefile b/src/src/Makefile new file mode 100644 index 00000000..5a90099a --- /dev/null +++ b/src/src/Makefile @@ -0,0 +1,1041 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# src/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + + + + +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/elfutils +pkgincludedir = $(includedir)/elfutils +pkglibdir = $(libdir)/elfutils +pkglibexecdir = $(libexecdir)/elfutils +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +DIST_COMMON = $(top_srcdir)/config/eu.am $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am ldlex.c ldscript.c \ + $(top_srcdir)/config/depcomp $(top_srcdir)/config/ylwrap \ + $(noinst_HEADERS) ChangeLog +bin_PROGRAMS = readelf$(EXEEXT) nm$(EXEEXT) size$(EXEEXT) \ + strip$(EXEEXT) ld$(EXEEXT) elflint$(EXEEXT) \ + findtextrel$(EXEEXT) addr2line$(EXEEXT) elfcmp$(EXEEXT) \ + objdump$(EXEEXT) ranlib$(EXEEXT) strings$(EXEEXT) ar$(EXEEXT) \ + unstrip$(EXEEXT) stack$(EXEEXT) +noinst_PROGRAMS = $(am__EXEEXT_1) +# We never build this library but we need to get the dependency files +# of all the linker backends that might be used in a non-generic linker. +#am__append_1 = libdummy.a +# -ldl is always needed for libebl. +#am__append_2 = libld_elf.a +#am_libld_elf_i386_pic_a_OBJECTS = +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/biarch.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/zip.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libar_a_AR = $(AR) $(ARFLAGS) +libar_a_LIBADD = +am_libar_a_OBJECTS = arlib.$(OBJEXT) arlib2.$(OBJEXT) \ + arlib-argp.$(OBJEXT) +libar_a_OBJECTS = $(am_libar_a_OBJECTS) +libdummy_a_AR = $(AR) $(ARFLAGS) +libdummy_a_LIBADD = +am__libdummy_a_SOURCES_DIST = i386_ld.c +#am_libdummy_a_OBJECTS = i386_ld.$(OBJEXT) +libdummy_a_OBJECTS = $(am_libdummy_a_OBJECTS) +libld_elf_a_AR = $(AR) $(ARFLAGS) +libld_elf_a_LIBADD = +am__libld_elf_a_SOURCES_DIST = $(base_cpu)_ld.c +#am_libld_elf_a_OBJECTS = $(base_cpu)_ld.$(OBJEXT) +libld_elf_a_OBJECTS = $(am_libld_elf_a_OBJECTS) +libld_elf_i386_pic_a_AR = $(AR) $(ARFLAGS) +libld_elf_i386_pic_a_LIBADD = +libld_elf_i386_pic_a_OBJECTS = $(am_libld_elf_i386_pic_a_OBJECTS) +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" +am__EXEEXT_1 = libld_elf_i386.so$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +addr2line_SOURCES = addr2line.c +addr2line_OBJECTS = addr2line.$(OBJEXT) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = ../libdw/libdw.so +#am__DEPENDENCIES_2 = ../libdw/libdw.a \ +# $(am__DEPENDENCIES_1) $(libelf) $(libebl) +addr2line_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) +ar_SOURCES = ar.c +ar_OBJECTS = ar.$(OBJEXT) +ar_DEPENDENCIES = libar.a $(libelf) $(libeu) +elfcmp_SOURCES = elfcmp.c +elfcmp_OBJECTS = elfcmp.$(OBJEXT) +elfcmp_DEPENDENCIES = $(libebl) $(libelf) +elflint_SOURCES = elflint.c +elflint_OBJECTS = elflint.$(OBJEXT) +elflint_DEPENDENCIES = $(libebl) $(libelf) $(libeu) +findtextrel_SOURCES = findtextrel.c +findtextrel_OBJECTS = findtextrel.$(OBJEXT) +findtextrel_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) +am_ld_OBJECTS = ld.$(OBJEXT) ldgeneric.$(OBJEXT) ldlex.$(OBJEXT) \ + ldscript.$(OBJEXT) symbolhash.$(OBJEXT) sectionhash.$(OBJEXT) \ + versionhash.$(OBJEXT) +ld_OBJECTS = $(am_ld_OBJECTS) +ld_DEPENDENCIES = $(libebl) $(libelf) $(libeu) $(am__append_2) +ld_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(ld_LDFLAGS) $(LDFLAGS) -o \ + $@ +am_libld_elf_i386_so_OBJECTS = +libld_elf_i386_so_OBJECTS = $(am_libld_elf_i386_so_OBJECTS) +libld_elf_i386_so_LDADD = $(LDADD) +nm_SOURCES = nm.c +nm_OBJECTS = nm.$(OBJEXT) +nm_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libebl) $(libelf) $(libeu) \ + $(am__DEPENDENCIES_1) +objdump_SOURCES = objdump.c +objdump_OBJECTS = objdump.$(OBJEXT) +objdump_DEPENDENCIES = $(libasm) $(libebl) $(libelf) $(libeu) +ranlib_SOURCES = ranlib.c +ranlib_OBJECTS = ranlib.$(OBJEXT) +ranlib_DEPENDENCIES = libar.a $(libelf) $(libeu) +readelf_SOURCES = readelf.c +readelf_OBJECTS = readelf.$(OBJEXT) +readelf_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libebl) $(libelf) \ + $(libeu) +size_SOURCES = size.c +size_OBJECTS = size.$(OBJEXT) +size_DEPENDENCIES = $(libelf) $(libeu) +stack_SOURCES = stack.c +stack_OBJECTS = stack.$(OBJEXT) +stack_DEPENDENCIES = $(libebl) $(libelf) $(am__DEPENDENCIES_2) \ + $(libeu) $(am__DEPENDENCIES_1) +strings_SOURCES = strings.c +strings_OBJECTS = strings.$(OBJEXT) +strings_DEPENDENCIES = $(libelf) $(libeu) +strip_SOURCES = strip.c +strip_OBJECTS = strip.$(OBJEXT) +strip_DEPENDENCIES = $(libebl) $(libelf) $(libeu) +unstrip_SOURCES = unstrip.c +unstrip_OBJECTS = unstrip.$(OBJEXT) +unstrip_DEPENDENCIES = $(libebl) $(libelf) $(am__DEPENDENCIES_2) \ + $(libeu) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I. -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +am__skiplex = test -f $@ || +LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) +AM_V_LEX = $(am__v_LEX_$(V)) +am__v_LEX_ = $(am__v_LEX_$(AM_DEFAULT_VERBOSITY)) +am__v_LEX_0 = @echo " LEX " $@; +am__v_LEX_1 = +YLWRAP = $(top_srcdir)/config/ylwrap +am__skipyacc = test -f $@ || +am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ + -e s/c++$$/h++/ -e s/c$$/h/ +YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) +AM_V_YACC = $(am__v_YACC_$(V)) +am__v_YACC_ = $(am__v_YACC_$(AM_DEFAULT_VERBOSITY)) +am__v_YACC_0 = @echo " YACC " $@; +am__v_YACC_1 = +SOURCES = $(libar_a_SOURCES) $(libdummy_a_SOURCES) \ + $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \ + addr2line.c ar.c elfcmp.c elflint.c findtextrel.c \ + $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c objdump.c \ + ranlib.c readelf.c size.c stack.c strings.c strip.c unstrip.c +DIST_SOURCES = $(libar_a_SOURCES) $(am__libdummy_a_SOURCES_DIST) \ + $(am__libld_elf_a_SOURCES_DIST) \ + $(libld_elf_i386_pic_a_SOURCES) addr2line.c ar.c elfcmp.c \ + elflint.c findtextrel.c $(ld_SOURCES) \ + $(libld_elf_i386_so_SOURCES) nm.c objdump.c ranlib.c readelf.c \ + size.c stack.c strings.c strip.c unstrip.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing aclocal-1.14 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 1 +AR = ar +AUTOCONF = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing autoconf +AUTOHEADER = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing autoheader +AUTOMAKE = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing automake-1.14 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CC_BIARCH = gcc -m32 +CFLAGS = -g -O2 +CPP = gcc -E +CPPFLAGS = +CYGPATH_W = echo +DEBUGPRED = 0 +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' \ + $(YYDEBUG) -DDEBUGPRED=0 -DSRCDIR=\"$(shell cd \ + $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\" +DEPDIR = .deps +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +GETTEXT_MACRO_VERSION = 0.18 +GMSGFMT = /usr/bin/msgfmt +GMSGFMT_015 = /usr/bin/msgfmt +GREP = /bin/grep +HAVE_VALGRIND = +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LDFLAGS = +LEX = flex +LEXLIB = -lfl +LEX_OUTPUT_ROOT = lex.yy +LIBEBL_SUBDIR = elfutils +LIBOBJS = +LIBS = +LTLIBOBJS = +MAINT = # +MAKEINFO = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing makeinfo +MKDIR_P = /bin/mkdir -p +MODVERSION = Build on enh.mtv.corp.google.com 2015-02-18T19:32:04-0800 +MSGFMT = /usr/bin/msgfmt +MSGFMT_015 = /usr/bin/msgfmt +MSGMERGE = /usr/bin/msgmerge +NM = nm +OBJEXT = o +PACKAGE = elfutils +PACKAGE_BUGREPORT = https://bugzilla.redhat.com/ +PACKAGE_NAME = elfutils +PACKAGE_STRING = elfutils 0.161 +PACKAGE_TARNAME = elfutils +PACKAGE_URL = +PACKAGE_VERSION = 0.161 +PATH_SEPARATOR = : +RANLIB = ranlib +READELF = readelf +SET_MAKE = +SHELL = /bin/sh +STRIP = +USE_NLS = yes +VERSION = 0.161 +XGETTEXT = /usr/bin/xgettext +XGETTEXT_015 = /usr/bin/xgettext +XGETTEXT_EXTRA_OPTIONS = +YACC = bison -y -d +YFLAGS = +abs_builddir = /huge-ssd/aosp-arm64/external/elfutils/src/src +abs_srcdir = /huge-ssd/aosp-arm64/external/elfutils/src/src +abs_top_builddir = /huge-ssd/aosp-arm64/external/elfutils/src +abs_top_srcdir = /huge-ssd/aosp-arm64/external/elfutils/src +ac_ct_AR = ar +ac_ct_CC = gcc +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +base_cpu = none +bindir = ${exec_prefix}/bin +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +eu_version = 161 +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target_alias = +top_build_prefix = ../ +top_builddir = .. +top_srcdir = .. +zip_LIBS = -lz +AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \ + -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ + -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ + -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm +AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ + $(if $($(*F)_no_Werror),,-Werror) \ + $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ + $($(*F)_CFLAGS) + +COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE)) +CLEANFILES = *.gcno *.gcda make-debug-archive none_ld.os \ + $(ld_modules:.c=.os) *.gconv +textrel_msg = echo "WARNING: TEXTREL found in '$@'" +#textrel_found = $(textrel_msg) +textrel_found = $(textrel_msg); exit 1 +textrel_check = if $(READELF) -d $@ | fgrep -q TEXTREL; then $(textrel_found); fi +AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw +AM_YFLAGS = -pld +AM_LFLAGS = -Pld -olex.yy.c +native_ld = @native_ld@ +ld_dsos = libld_elf_i386_pic.a +noinst_LIBRARIES = libld_elf.a libar.a $(ld_dsos) \ + $(am__append_1) +#noinst_LIBRARIES = libld_elf.a libar.a $(am__append_1) +#native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu) +#libdummy_a_SOURCES = i386_ld.c +ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \ + versionhash.c + +libar_a_SOURCES = arlib.c arlib2.c arlib-argp.c +noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \ + ldscript.h xelf.h unaligned.h + +EXTRA_DIST = elf32-i386.script libld_elf_i386.map $(ld_modules) \ + arlib.h debugpred.h make-debug-archive.in +ld_modules = i386_ld.c +bin_SCRIPTS = make-debug-archive +libasm = ../libasm/libasm.so +#libasm = ../libasm/libasm.a +libdw = ../libdw/libdw.so +#libdw = ../libdw/libdw.a $(zip_LIBS) $(libelf) $(libebl) -ldl +libelf = ../libelf/libelf.so +#libelf = ../libelf/libelf.a +libebl = ../libebl/libebl.a +libeu = ../lib/libeu.a +demanglelib = -lstdc++ + +# XXX While the file is not finished, don't warn about this +ldgeneric_no_Wunused = yes +readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl +nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl \ + $(demanglelib) + +size_LDADD = $(libelf) $(libeu) +strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl +ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl $(am__append_2) +ld_LDFLAGS = -rdynamic +elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl +findtextrel_LDADD = $(libdw) $(libelf) +addr2line_LDADD = $(libdw) $(libelf) +elfcmp_LDADD = $(libebl) $(libelf) -ldl +objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) -ldl +ranlib_LDADD = libar.a $(libelf) $(libeu) +strings_LDADD = $(libelf) $(libeu) +ar_LDADD = libar.a $(libelf) $(libeu) +unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl +stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl $(demanglelib) +ldlex_no_Werror = yes + +# Machine-specific linker code. +#libld_elf_a_SOURCES := $(base_cpu)_ld.c +libld_elf_i386_pic_a_SOURCES = +am_libld_elf_i386_pic_a_OBJECTS = i386_ld.os +libld_elf_i386_so_SOURCES = +MAINTAINERCLEANFILES = ldlex.c ldscript.c ldscript.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .l .o .obj .y +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(top_srcdir)/config/eu.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/config/eu.am: + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libar.a: $(libar_a_OBJECTS) $(libar_a_DEPENDENCIES) $(EXTRA_libar_a_DEPENDENCIES) + $(AM_V_at)-rm -f libar.a + $(AM_V_AR)$(libar_a_AR) libar.a $(libar_a_OBJECTS) $(libar_a_LIBADD) + $(AM_V_at)$(RANLIB) libar.a + +libdummy.a: $(libdummy_a_OBJECTS) $(libdummy_a_DEPENDENCIES) $(EXTRA_libdummy_a_DEPENDENCIES) + $(AM_V_at)-rm -f libdummy.a + $(AM_V_AR)$(libdummy_a_AR) libdummy.a $(libdummy_a_OBJECTS) $(libdummy_a_LIBADD) + $(AM_V_at)$(RANLIB) libdummy.a + +libld_elf.a: $(libld_elf_a_OBJECTS) $(libld_elf_a_DEPENDENCIES) $(EXTRA_libld_elf_a_DEPENDENCIES) + $(AM_V_at)-rm -f libld_elf.a + $(AM_V_AR)$(libld_elf_a_AR) libld_elf.a $(libld_elf_a_OBJECTS) $(libld_elf_a_LIBADD) + $(AM_V_at)$(RANLIB) libld_elf.a + +libld_elf_i386_pic.a: $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_DEPENDENCIES) $(EXTRA_libld_elf_i386_pic_a_DEPENDENCIES) + $(AM_V_at)-rm -f libld_elf_i386_pic.a + $(AM_V_AR)$(libld_elf_i386_pic_a_AR) libld_elf_i386_pic.a $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_LIBADD) + $(AM_V_at)$(RANLIB) libld_elf_i386_pic.a +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES) $(EXTRA_addr2line_DEPENDENCIES) + @rm -f addr2line$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS) + +ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES) $(EXTRA_ar_DEPENDENCIES) + @rm -f ar$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ar_OBJECTS) $(ar_LDADD) $(LIBS) + +elfcmp$(EXEEXT): $(elfcmp_OBJECTS) $(elfcmp_DEPENDENCIES) $(EXTRA_elfcmp_DEPENDENCIES) + @rm -f elfcmp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elfcmp_OBJECTS) $(elfcmp_LDADD) $(LIBS) + +elflint$(EXEEXT): $(elflint_OBJECTS) $(elflint_DEPENDENCIES) $(EXTRA_elflint_DEPENDENCIES) + @rm -f elflint$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(elflint_OBJECTS) $(elflint_LDADD) $(LIBS) + +findtextrel$(EXEEXT): $(findtextrel_OBJECTS) $(findtextrel_DEPENDENCIES) $(EXTRA_findtextrel_DEPENDENCIES) + @rm -f findtextrel$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(findtextrel_OBJECTS) $(findtextrel_LDADD) $(LIBS) + +ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES) $(EXTRA_ld_DEPENDENCIES) + @rm -f ld$(EXEEXT) + $(AM_V_CCLD)$(ld_LINK) $(ld_OBJECTS) $(ld_LDADD) $(LIBS) + +#libld_elf_i386.so$(EXEEXT): $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_DEPENDENCIES) $(EXTRA_libld_elf_i386_so_DEPENDENCIES) +# @rm -f libld_elf_i386.so$(EXEEXT) +# $(AM_V_CCLD)$(LINK) $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_LDADD) $(LIBS) + +nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES) $(EXTRA_nm_DEPENDENCIES) + @rm -f nm$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nm_OBJECTS) $(nm_LDADD) $(LIBS) + +objdump$(EXEEXT): $(objdump_OBJECTS) $(objdump_DEPENDENCIES) $(EXTRA_objdump_DEPENDENCIES) + @rm -f objdump$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(objdump_OBJECTS) $(objdump_LDADD) $(LIBS) + +ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES) $(EXTRA_ranlib_DEPENDENCIES) + @rm -f ranlib$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS) + +readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES) $(EXTRA_readelf_DEPENDENCIES) + @rm -f readelf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS) + +size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES) $(EXTRA_size_DEPENDENCIES) + @rm -f size$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(size_OBJECTS) $(size_LDADD) $(LIBS) + +stack$(EXEEXT): $(stack_OBJECTS) $(stack_DEPENDENCIES) $(EXTRA_stack_DEPENDENCIES) + @rm -f stack$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stack_OBJECTS) $(stack_LDADD) $(LIBS) + +strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES) $(EXTRA_strings_DEPENDENCIES) + @rm -f strings$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(strings_OBJECTS) $(strings_LDADD) $(LIBS) + +strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES) $(EXTRA_strip_DEPENDENCIES) + @rm -f strip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(strip_OBJECTS) $(strip_LDADD) $(LIBS) + +unstrip$(EXEEXT): $(unstrip_OBJECTS) $(unstrip_DEPENDENCIES) $(EXTRA_unstrip_DEPENDENCIES) + @rm -f unstrip$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(unstrip_OBJECTS) $(unstrip_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +installcheck-binSCRIPTS: $(bin_SCRIPTS) + bad=0; pid=$$$$; list="$(bin_SCRIPTS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | sed 's,^.*/,,;$(transform)'`; \ + for opt in --help --version; do \ + if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \ + 2>c$${pid}_.err </dev/null \ + && test -n "`cat c$${pid}_.out`" \ + && test -z "`cat c$${pid}_.err`"; then :; \ + else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/$(base_cpu)_ld.Po +include ./$(DEPDIR)/addr2line.Po +include ./$(DEPDIR)/ar.Po +include ./$(DEPDIR)/arlib-argp.Po +include ./$(DEPDIR)/arlib.Po +include ./$(DEPDIR)/arlib2.Po +include ./$(DEPDIR)/elfcmp.Po +include ./$(DEPDIR)/elflint.Po +include ./$(DEPDIR)/findtextrel.Po +include ./$(DEPDIR)/i386_ld.Po +include ./$(DEPDIR)/ld.Po +include ./$(DEPDIR)/ldgeneric.Po +include ./$(DEPDIR)/ldlex.Po +include ./$(DEPDIR)/ldscript.Po +include ./$(DEPDIR)/nm.Po +include ./$(DEPDIR)/objdump.Po +include ./$(DEPDIR)/ranlib.Po +include ./$(DEPDIR)/readelf.Po +include ./$(DEPDIR)/sectionhash.Po +include ./$(DEPDIR)/size.Po +include ./$(DEPDIR)/stack.Po +include ./$(DEPDIR)/strings.Po +include ./$(DEPDIR)/strip.Po +include ./$(DEPDIR)/symbolhash.Po +include ./$(DEPDIR)/unstrip.Po +include ./$(DEPDIR)/versionhash.Po + +.c.o: + $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# $(AM_V_CC)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(AM_V_CC_no)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# $(AM_V_CC)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.l.c: + $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) + +.y.c: + $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(SCRIPTS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -rm -f ldlex.c + -rm -f ldscript.c + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS install-binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: installcheck-binPROGRAMS installcheck-binSCRIPTS + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-binSCRIPTS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installcheck-binPROGRAMS \ + installcheck-binSCRIPTS installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS + + +%.os: %.c %.o + if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \ + -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \ + then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \ + rm -f "$(DEPDIR)/$*.Tpo"; \ + else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ + fi +# $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $< + +ldlex.o: ldscript.c +ldscript.h: ldscript.c +libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map + $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \ + $(libelf) $(libeu) \ + -Wl,--version-script,$(srcdir)/libld_elf_i386.map + @$(textrel_check) + +# Special rule to make it possible to define libld_elf_a_SOURCES as we do. +# Otherwise make would complain. +.deps/none_ld.Po: none_ld.os + -: + +installcheck-binPROGRAMS: $(bin_PROGRAMS) + bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \ + $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \ + && test -n "`cat c$${pid}_.out`" \ + && test -z "`cat c$${pid}_.err`"; then :; \ + else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad + +make-debug-archive: $(srcdir)/make-debug-archive.in + UNSTRIP=$(bindir)/`echo unstrip | sed '$(transform)'`; \ + AR=$(bindir)/`echo ar | sed '$(transform)'`; \ + sed -e "s,[@]UNSTRIP[@],$$UNSTRIP,g" -e "s,[@]AR[@],$$AR,g" \ + -e "s%[@]PACKAGE_NAME[@]%$(PACKAGE_NAME)%g" \ + -e "s%[@]PACKAGE_VERSION[@]%$(PACKAGE_VERSION)%g" \ + $(srcdir)/make-debug-archive.in > $@.new + chmod +x $@.new + mv -f $@.new $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/src/Makefile.am b/src/src/Makefile.am index dc835cbd..7a253745 100644 --- a/src/src/Makefile.am +++ b/src/src/Makefile.am @@ -1,40 +1,30 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 1996-2012 Red Hat, Inc. -## This file is part of Red Hat elfutils. +## Copyright (C) 1996-2014 Red Hat, Inc. +## This file is part of elfutils. ## -## Red Hat elfutils is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by the -## Free Software Foundation; version 2 of the License. +## This file is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. ## -## Red Hat elfutils is distributed in the hope that it will be useful, but +## elfutils is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. ## -## You should have received a copy of the GNU General Public License along -## with Red Hat elfutils; if not, write to the Free Software Foundation, -## Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. -## -## Red Hat elfutils is an included package of the Open Invention Network. -## An included package of the Open Invention Network is a package for which -## Open Invention Network licensees cross-license their patents. No patent -## license is granted, either expressly or impliedly, by designation as an -## included package. Should you wish to participate in the Open Invention -## Network licensing program, please visit www.openinventionnetwork.com -## <http://www.openinventionnetwork.com>. +## You should have received a copy of the GNU General Public License +## along with this program. If not, see <http://www.gnu.org/licenses/>. ## include $(top_srcdir)/config/eu.am DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRED@ \ -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\" -INCLUDES += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwfl \ - -I$(srcdir)/../libasm +AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ + -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ + -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw -no_mudflap.os = -fmudflap - YACC = @YACC@ -d AM_YFLAGS = -pld AM_LFLAGS = -Pld -olex.yy.c @@ -45,7 +35,7 @@ native_ld = @native_ld@ base_cpu = @base_cpu@ bin_PROGRAMS = readelf nm size strip ld elflint findtextrel addr2line \ - elfcmp objdump ranlib strings ar unstrip + elfcmp objdump ranlib strings ar unstrip stack ld_dsos = libld_elf_i386_pic.a @@ -96,33 +86,30 @@ if DEMANGLE demanglelib = -lstdc++ endif -nm_no_Wformat = yes -size_no_Wformat = yes -strings_no_Wformat = yes -addr2line_no_Wformat = yes # XXX While the file is not finished, don't warn about this ldgeneric_no_Wunused = yes -readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \ +readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl +nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl \ $(demanglelib) -size_LDADD = $(libelf) $(libeu) $(libmudflap) -strip_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -ld_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl +size_LDADD = $(libelf) $(libeu) +strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl +ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl if NATIVE_LD # -ldl is always needed for libebl. ld_LDADD += libld_elf.a endif ld_LDFLAGS = -rdynamic -elflint_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -findtextrel_LDADD = $(libdw) $(libelf) $(libmudflap) -addr2line_LDADD = $(libdw) $(libelf) $(libmudflap) -elfcmp_LDADD = $(libebl) $(libelf) $(libmudflap) -ldl -objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) -strings_LDADD = $(libelf) $(libeu) $(libmudflap) -ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) -unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl +elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl +findtextrel_LDADD = $(libdw) $(libelf) +addr2line_LDADD = $(libdw) $(libelf) +elfcmp_LDADD = $(libebl) $(libelf) -ldl +objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) -ldl +ranlib_LDADD = libar.a $(libelf) $(libeu) +strings_LDADD = $(libelf) $(libeu) +ar_LDADD = libar.a $(libelf) $(libeu) +unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl +stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl $(demanglelib) ldlex.o: ldscript.c ldlex_no_Werror = yes @@ -140,7 +127,7 @@ libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \ $(libelf) $(libeu) \ -Wl,--version-script,$(srcdir)/libld_elf_i386.map - $(textrel_check) + @$(textrel_check) endif # Special rule to make it possible to define libld_elf_a_SOURCES as we do. @@ -173,7 +160,7 @@ MAINTAINERCLEANFILES = ldlex.c ldscript.c ldscript.h make-debug-archive: $(srcdir)/make-debug-archive.in UNSTRIP=$(bindir)/`echo unstrip | sed '$(transform)'`; \ AR=$(bindir)/`echo ar | sed '$(transform)'`; \ - sed -e "s,@UNSTRIP@,$$UNSTRIP,g" -e "s,@AR@,$$AR,g" \ + sed -e "s,[@]UNSTRIP[@],$$UNSTRIP,g" -e "s,[@]AR[@],$$AR,g" \ -e "s%[@]PACKAGE_NAME[@]%$(PACKAGE_NAME)%g" \ -e "s%[@]PACKAGE_VERSION[@]%$(PACKAGE_VERSION)%g" \ $(srcdir)/make-debug-archive.in > $@.new diff --git a/src/src/Makefile.in b/src/src/Makefile.in index bccaaf95..19009c7a 100644 --- a/src/src/Makefile.in +++ b/src/src/Makefile.in @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -19,6 +18,51 @@ VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -37,25 +81,26 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(top_srcdir)/config/eu.am ChangeLog \ - ldlex.c ldscript.c ylwrap -@MUDFLAP_TRUE@am__append_1 = -fmudflap +DIST_COMMON = $(top_srcdir)/config/eu.am $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am ldlex.c ldscript.c \ + $(top_srcdir)/config/depcomp $(top_srcdir)/config/ylwrap \ + $(noinst_HEADERS) ChangeLog bin_PROGRAMS = readelf$(EXEEXT) nm$(EXEEXT) size$(EXEEXT) \ strip$(EXEEXT) ld$(EXEEXT) elflint$(EXEEXT) \ findtextrel$(EXEEXT) addr2line$(EXEEXT) elfcmp$(EXEEXT) \ objdump$(EXEEXT) ranlib$(EXEEXT) strings$(EXEEXT) ar$(EXEEXT) \ - unstrip$(EXEEXT) + unstrip$(EXEEXT) stack$(EXEEXT) @NATIVE_LD_FALSE@noinst_PROGRAMS = $(am__EXEEXT_1) # We never build this library but we need to get the dependency files # of all the linker backends that might be used in a non-generic linker. -@NEVER_TRUE@am__append_2 = libdummy.a +@NEVER_TRUE@am__append_1 = libdummy.a # -ldl is always needed for libebl. -@NATIVE_LD_TRUE@am__append_3 = libld_elf.a +@NATIVE_LD_TRUE@am__append_2 = libld_elf.a @NATIVE_LD_TRUE@am_libld_elf_i386_pic_a_OBJECTS = subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/biarch.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/zip.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -65,8 +110,11 @@ CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) -AR = ar ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = libar_a_AR = $(AR) $(ARFLAGS) libar_a_LIBADD = am_libar_a_OBJECTS = arlib.$(OBJEXT) arlib2.$(OBJEXT) \ @@ -94,28 +142,24 @@ am__DEPENDENCIES_1 = @BUILD_STATIC_FALSE@am__DEPENDENCIES_2 = ../libdw/libdw.so @BUILD_STATIC_TRUE@am__DEPENDENCIES_2 = ../libdw/libdw.a \ @BUILD_STATIC_TRUE@ $(am__DEPENDENCIES_1) $(libelf) $(libebl) -addr2line_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) \ - $(am__DEPENDENCIES_1) +addr2line_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) ar_SOURCES = ar.c ar_OBJECTS = ar.$(OBJEXT) -ar_DEPENDENCIES = libar.a $(libelf) $(libeu) $(am__DEPENDENCIES_1) +ar_DEPENDENCIES = libar.a $(libelf) $(libeu) elfcmp_SOURCES = elfcmp.c elfcmp_OBJECTS = elfcmp.$(OBJEXT) -elfcmp_DEPENDENCIES = $(libebl) $(libelf) $(am__DEPENDENCIES_1) +elfcmp_DEPENDENCIES = $(libebl) $(libelf) elflint_SOURCES = elflint.c elflint_OBJECTS = elflint.$(OBJEXT) -elflint_DEPENDENCIES = $(libebl) $(libelf) $(libeu) \ - $(am__DEPENDENCIES_1) +elflint_DEPENDENCIES = $(libebl) $(libelf) $(libeu) findtextrel_SOURCES = findtextrel.c findtextrel_OBJECTS = findtextrel.$(OBJEXT) -findtextrel_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) \ - $(am__DEPENDENCIES_1) +findtextrel_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libelf) am_ld_OBJECTS = ld.$(OBJEXT) ldgeneric.$(OBJEXT) ldlex.$(OBJEXT) \ ldscript.$(OBJEXT) symbolhash.$(OBJEXT) sectionhash.$(OBJEXT) \ versionhash.$(OBJEXT) ld_OBJECTS = $(am_ld_OBJECTS) -ld_DEPENDENCIES = $(libebl) $(libelf) $(libeu) $(am__DEPENDENCIES_1) \ - $(am__append_3) +ld_DEPENDENCIES = $(libebl) $(libelf) $(libeu) $(am__append_2) ld_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(ld_LDFLAGS) $(LDFLAGS) -o \ $@ am_libld_elf_i386_so_OBJECTS = @@ -124,32 +168,34 @@ libld_elf_i386_so_LDADD = $(LDADD) nm_SOURCES = nm.c nm_OBJECTS = nm.$(OBJEXT) nm_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libebl) $(libelf) $(libeu) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) objdump_SOURCES = objdump.c objdump_OBJECTS = objdump.$(OBJEXT) -objdump_DEPENDENCIES = $(libasm) $(libebl) $(libelf) $(libeu) \ - $(am__DEPENDENCIES_1) +objdump_DEPENDENCIES = $(libasm) $(libebl) $(libelf) $(libeu) ranlib_SOURCES = ranlib.c ranlib_OBJECTS = ranlib.$(OBJEXT) -ranlib_DEPENDENCIES = libar.a $(libelf) $(libeu) $(am__DEPENDENCIES_1) +ranlib_DEPENDENCIES = libar.a $(libelf) $(libeu) readelf_SOURCES = readelf.c readelf_OBJECTS = readelf.$(OBJEXT) readelf_DEPENDENCIES = $(am__DEPENDENCIES_2) $(libebl) $(libelf) \ - $(libeu) $(am__DEPENDENCIES_1) + $(libeu) size_SOURCES = size.c size_OBJECTS = size.$(OBJEXT) -size_DEPENDENCIES = $(libelf) $(libeu) $(am__DEPENDENCIES_1) +size_DEPENDENCIES = $(libelf) $(libeu) +stack_SOURCES = stack.c +stack_OBJECTS = stack.$(OBJEXT) +stack_DEPENDENCIES = $(libebl) $(libelf) $(am__DEPENDENCIES_2) \ + $(libeu) $(am__DEPENDENCIES_1) strings_SOURCES = strings.c strings_OBJECTS = strings.$(OBJEXT) -strings_DEPENDENCIES = $(libelf) $(libeu) $(am__DEPENDENCIES_1) +strings_DEPENDENCIES = $(libelf) $(libeu) strip_SOURCES = strip.c strip_OBJECTS = strip.$(OBJEXT) -strip_DEPENDENCIES = $(libebl) $(libelf) $(libeu) \ - $(am__DEPENDENCIES_1) +strip_DEPENDENCIES = $(libebl) $(libelf) $(libeu) unstrip_SOURCES = unstrip.c unstrip_OBJECTS = unstrip.$(OBJEXT) unstrip_DEPENDENCIES = $(libebl) $(libelf) $(am__DEPENDENCIES_2) \ - $(libeu) $(am__DEPENDENCIES_1) + $(libeu) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -171,44 +217,106 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = @MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ || -LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) +LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) +AM_V_LEX = $(am__v_LEX_@AM_V@) +am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) +am__v_LEX_0 = @echo " LEX " $@; +am__v_LEX_1 = YLWRAP = $(top_srcdir)/config/ylwrap @MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || -YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) +am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ + -e s/c++$$/h++/ -e s/c$$/h/ +YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) +AM_V_YACC = $(am__v_YACC_@AM_V@) +am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) +am__v_YACC_0 = @echo " YACC " $@; +am__v_YACC_1 = SOURCES = $(libar_a_SOURCES) $(libdummy_a_SOURCES) \ $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \ addr2line.c ar.c elfcmp.c elflint.c findtextrel.c \ $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c objdump.c \ - ranlib.c readelf.c size.c strings.c strip.c unstrip.c + ranlib.c readelf.c size.c stack.c strings.c strip.c unstrip.c DIST_SOURCES = $(libar_a_SOURCES) $(am__libdummy_a_SOURCES_DIST) \ $(am__libld_elf_a_SOURCES_DIST) \ $(libld_elf_i386_pic_a_SOURCES) addr2line.c ar.c elfcmp.c \ elflint.c findtextrel.c $(ld_SOURCES) \ $(libld_elf_i386_so_SOURCES) nm.c objdump.c ranlib.c readelf.c \ - size.c strings.c strip.c unstrip.c + size.c stack.c strings.c strip.c unstrip.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ +CC_BIARCH = @CC_BIARCH@ CFLAGS = @CFLAGS@ +CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUGPRED = @DEBUGPRED@ @@ -219,10 +327,13 @@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ +EGREP = @EGREP@ EXEEXT = @EXEEXT@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_VALGRIND = @HAVE_VALGRIND@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -243,6 +354,7 @@ MODVERSION = @MODVERSION@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ +NM = @NM@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ @@ -253,6 +365,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ +READELF = @READELF@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ @@ -267,6 +380,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ @@ -316,32 +430,30 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ zip_LIBS = @zip_LIBS@ -INCLUDES = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \ +AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \ -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwfl \ - -I$(srcdir)/../libasm -AM_CFLAGS = -std=gnu99 -Wall -Wshadow $(if \ - $($(*F)_no_Werror),,-Werror) $(if \ - $($(*F)_no_Wunused),,-Wunused -Wextra) $(if \ - $($(*F)_no_Wformat),-Wno-format,-Wformat=2) $($(*F)_CFLAGS) \ - $(am__append_1) -@MUDFLAP_FALSE@libmudflap = -@MUDFLAP_TRUE@libmudflap = -lmudflap -COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage $(no_mudflap.os),\ - $(COMPILE)) - + -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ + -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm +AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ + $(if $($(*F)_no_Werror),,-Werror) \ + $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ + $($(*F)_CFLAGS) + +COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE)) CLEANFILES = *.gcno *.gcda make-debug-archive none_ld.os \ $(ld_modules:.c=.os) *.gconv -textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi +textrel_msg = echo "WARNING: TEXTREL found in '$@'" +@FATAL_TEXTREL_FALSE@textrel_found = $(textrel_msg) +@FATAL_TEXTREL_TRUE@textrel_found = $(textrel_msg); exit 1 +textrel_check = if $(READELF) -d $@ | fgrep -q TEXTREL; then $(textrel_found); fi AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw -no_mudflap.os = -fmudflap AM_YFLAGS = -pld AM_LFLAGS = -Pld -olex.yy.c native_ld = @native_ld@ ld_dsos = libld_elf_i386_pic.a @NATIVE_LD_FALSE@noinst_LIBRARIES = libld_elf.a libar.a $(ld_dsos) \ -@NATIVE_LD_FALSE@ $(am__append_2) -@NATIVE_LD_TRUE@noinst_LIBRARIES = libld_elf.a libar.a $(am__append_2) +@NATIVE_LD_FALSE@ $(am__append_1) +@NATIVE_LD_TRUE@noinst_LIBRARIES = libld_elf.a libar.a $(am__append_1) @NATIVE_LD_TRUE@native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu) @NEVER_TRUE@libdummy_a_SOURCES = i386_ld.c ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \ @@ -364,30 +476,27 @@ bin_SCRIPTS = make-debug-archive libebl = ../libebl/libebl.a libeu = ../lib/libeu.a @DEMANGLE_TRUE@demanglelib = -lstdc++ -nm_no_Wformat = yes -size_no_Wformat = yes -strings_no_Wformat = yes -addr2line_no_Wformat = yes + # XXX While the file is not finished, don't warn about this ldgeneric_no_Wunused = yes -readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \ +readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl +nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl \ $(demanglelib) -size_LDADD = $(libelf) $(libeu) $(libmudflap) -strip_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -ld_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl \ - $(am__append_3) +size_LDADD = $(libelf) $(libeu) +strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl +ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl $(am__append_2) ld_LDFLAGS = -rdynamic -elflint_LDADD = $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -findtextrel_LDADD = $(libdw) $(libelf) $(libmudflap) -addr2line_LDADD = $(libdw) $(libelf) $(libmudflap) -elfcmp_LDADD = $(libebl) $(libelf) $(libmudflap) -ldl -objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) $(libmudflap) -ldl -ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) -strings_LDADD = $(libelf) $(libeu) $(libmudflap) -ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap) -unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl +elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl +findtextrel_LDADD = $(libdw) $(libelf) +addr2line_LDADD = $(libdw) $(libelf) +elfcmp_LDADD = $(libebl) $(libelf) -ldl +objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) -ldl +ranlib_LDADD = libar.a $(libelf) $(libeu) +strings_LDADD = $(libelf) $(libeu) +ar_LDADD = libar.a $(libelf) $(libeu) +unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl +stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) -ldl $(demanglelib) ldlex_no_Werror = yes # Machine-specific linker code. @@ -421,6 +530,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; +$(top_srcdir)/config/eu.am: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh @@ -433,32 +543,40 @@ $(am__aclocal_m4_deps): clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libar.a: $(libar_a_OBJECTS) $(libar_a_DEPENDENCIES) - -rm -f libar.a - $(libar_a_AR) libar.a $(libar_a_OBJECTS) $(libar_a_LIBADD) - $(RANLIB) libar.a -libdummy.a: $(libdummy_a_OBJECTS) $(libdummy_a_DEPENDENCIES) - -rm -f libdummy.a - $(libdummy_a_AR) libdummy.a $(libdummy_a_OBJECTS) $(libdummy_a_LIBADD) - $(RANLIB) libdummy.a -libld_elf.a: $(libld_elf_a_OBJECTS) $(libld_elf_a_DEPENDENCIES) - -rm -f libld_elf.a - $(libld_elf_a_AR) libld_elf.a $(libld_elf_a_OBJECTS) $(libld_elf_a_LIBADD) - $(RANLIB) libld_elf.a -libld_elf_i386_pic.a: $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_DEPENDENCIES) - -rm -f libld_elf_i386_pic.a - $(libld_elf_i386_pic_a_AR) libld_elf_i386_pic.a $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_LIBADD) - $(RANLIB) libld_elf_i386_pic.a + +libar.a: $(libar_a_OBJECTS) $(libar_a_DEPENDENCIES) $(EXTRA_libar_a_DEPENDENCIES) + $(AM_V_at)-rm -f libar.a + $(AM_V_AR)$(libar_a_AR) libar.a $(libar_a_OBJECTS) $(libar_a_LIBADD) + $(AM_V_at)$(RANLIB) libar.a + +libdummy.a: $(libdummy_a_OBJECTS) $(libdummy_a_DEPENDENCIES) $(EXTRA_libdummy_a_DEPENDENCIES) + $(AM_V_at)-rm -f libdummy.a + $(AM_V_AR)$(libdummy_a_AR) libdummy.a $(libdummy_a_OBJECTS) $(libdummy_a_LIBADD) + $(AM_V_at)$(RANLIB) libdummy.a + +libld_elf.a: $(libld_elf_a_OBJECTS) $(libld_elf_a_DEPENDENCIES) $(EXTRA_libld_elf_a_DEPENDENCIES) + $(AM_V_at)-rm -f libld_elf.a + $(AM_V_AR)$(libld_elf_a_AR) libld_elf.a $(libld_elf_a_OBJECTS) $(libld_elf_a_LIBADD) + $(AM_V_at)$(RANLIB) libld_elf.a + +libld_elf_i386_pic.a: $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_DEPENDENCIES) $(EXTRA_libld_elf_i386_pic_a_DEPENDENCIES) + $(AM_V_at)-rm -f libld_elf_i386_pic.a + $(AM_V_AR)$(libld_elf_i386_pic_a_AR) libld_elf_i386_pic.a $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_LIBADD) + $(AM_V_at)$(RANLIB) libld_elf_i386_pic.a install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p; \ - then echo "$$p"; echo "$$p"; else :; fi; \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ - sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ @@ -479,7 +597,8 @@ uninstall-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' `; \ + -e 's/$$/$(EXEEXT)/' \ + `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files @@ -489,55 +608,77 @@ clean-binPROGRAMS: clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) -addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES) + +addr2line$(EXEEXT): $(addr2line_OBJECTS) $(addr2line_DEPENDENCIES) $(EXTRA_addr2line_DEPENDENCIES) @rm -f addr2line$(EXEEXT) - $(LINK) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS) -ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(addr2line_OBJECTS) $(addr2line_LDADD) $(LIBS) + +ar$(EXEEXT): $(ar_OBJECTS) $(ar_DEPENDENCIES) $(EXTRA_ar_DEPENDENCIES) @rm -f ar$(EXEEXT) - $(LINK) $(ar_OBJECTS) $(ar_LDADD) $(LIBS) -elfcmp$(EXEEXT): $(elfcmp_OBJECTS) $(elfcmp_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(ar_OBJECTS) $(ar_LDADD) $(LIBS) + +elfcmp$(EXEEXT): $(elfcmp_OBJECTS) $(elfcmp_DEPENDENCIES) $(EXTRA_elfcmp_DEPENDENCIES) @rm -f elfcmp$(EXEEXT) - $(LINK) $(elfcmp_OBJECTS) $(elfcmp_LDADD) $(LIBS) -elflint$(EXEEXT): $(elflint_OBJECTS) $(elflint_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(elfcmp_OBJECTS) $(elfcmp_LDADD) $(LIBS) + +elflint$(EXEEXT): $(elflint_OBJECTS) $(elflint_DEPENDENCIES) $(EXTRA_elflint_DEPENDENCIES) @rm -f elflint$(EXEEXT) - $(LINK) $(elflint_OBJECTS) $(elflint_LDADD) $(LIBS) -findtextrel$(EXEEXT): $(findtextrel_OBJECTS) $(findtextrel_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(elflint_OBJECTS) $(elflint_LDADD) $(LIBS) + +findtextrel$(EXEEXT): $(findtextrel_OBJECTS) $(findtextrel_DEPENDENCIES) $(EXTRA_findtextrel_DEPENDENCIES) @rm -f findtextrel$(EXEEXT) - $(LINK) $(findtextrel_OBJECTS) $(findtextrel_LDADD) $(LIBS) -ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(findtextrel_OBJECTS) $(findtextrel_LDADD) $(LIBS) + +ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES) $(EXTRA_ld_DEPENDENCIES) @rm -f ld$(EXEEXT) - $(ld_LINK) $(ld_OBJECTS) $(ld_LDADD) $(LIBS) -@NATIVE_LD_TRUE@libld_elf_i386.so$(EXEEXT): $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_DEPENDENCIES) + $(AM_V_CCLD)$(ld_LINK) $(ld_OBJECTS) $(ld_LDADD) $(LIBS) + +@NATIVE_LD_TRUE@libld_elf_i386.so$(EXEEXT): $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_DEPENDENCIES) $(EXTRA_libld_elf_i386_so_DEPENDENCIES) @NATIVE_LD_TRUE@ @rm -f libld_elf_i386.so$(EXEEXT) -@NATIVE_LD_TRUE@ $(LINK) $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_LDADD) $(LIBS) -nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES) +@NATIVE_LD_TRUE@ $(AM_V_CCLD)$(LINK) $(libld_elf_i386_so_OBJECTS) $(libld_elf_i386_so_LDADD) $(LIBS) + +nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES) $(EXTRA_nm_DEPENDENCIES) @rm -f nm$(EXEEXT) - $(LINK) $(nm_OBJECTS) $(nm_LDADD) $(LIBS) -objdump$(EXEEXT): $(objdump_OBJECTS) $(objdump_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(nm_OBJECTS) $(nm_LDADD) $(LIBS) + +objdump$(EXEEXT): $(objdump_OBJECTS) $(objdump_DEPENDENCIES) $(EXTRA_objdump_DEPENDENCIES) @rm -f objdump$(EXEEXT) - $(LINK) $(objdump_OBJECTS) $(objdump_LDADD) $(LIBS) -ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(objdump_OBJECTS) $(objdump_LDADD) $(LIBS) + +ranlib$(EXEEXT): $(ranlib_OBJECTS) $(ranlib_DEPENDENCIES) $(EXTRA_ranlib_DEPENDENCIES) @rm -f ranlib$(EXEEXT) - $(LINK) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS) -readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(ranlib_OBJECTS) $(ranlib_LDADD) $(LIBS) + +readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES) $(EXTRA_readelf_DEPENDENCIES) @rm -f readelf$(EXEEXT) - $(LINK) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS) -size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS) + +size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES) $(EXTRA_size_DEPENDENCIES) @rm -f size$(EXEEXT) - $(LINK) $(size_OBJECTS) $(size_LDADD) $(LIBS) -strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(size_OBJECTS) $(size_LDADD) $(LIBS) + +stack$(EXEEXT): $(stack_OBJECTS) $(stack_DEPENDENCIES) $(EXTRA_stack_DEPENDENCIES) + @rm -f stack$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(stack_OBJECTS) $(stack_LDADD) $(LIBS) + +strings$(EXEEXT): $(strings_OBJECTS) $(strings_DEPENDENCIES) $(EXTRA_strings_DEPENDENCIES) @rm -f strings$(EXEEXT) - $(LINK) $(strings_OBJECTS) $(strings_LDADD) $(LIBS) -strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(strings_OBJECTS) $(strings_LDADD) $(LIBS) + +strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES) $(EXTRA_strip_DEPENDENCIES) @rm -f strip$(EXEEXT) - $(LINK) $(strip_OBJECTS) $(strip_LDADD) $(LIBS) -unstrip$(EXEEXT): $(unstrip_OBJECTS) $(unstrip_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(strip_OBJECTS) $(strip_LDADD) $(LIBS) + +unstrip$(EXEEXT): $(unstrip_OBJECTS) $(unstrip_DEPENDENCIES) $(EXTRA_unstrip_DEPENDENCIES) @rm -f unstrip$(EXEEXT) - $(LINK) $(unstrip_OBJECTS) $(unstrip_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(unstrip_OBJECTS) $(unstrip_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ @@ -565,9 +706,7 @@ uninstall-binSCRIPTS: @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(bindir)" && rm -f $$files + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) installcheck-binSCRIPTS: $(bin_SCRIPTS) bad=0; pid=$$$$; list="$(bin_SCRIPTS)"; for p in $$list; do \ @@ -610,6 +749,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readelf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sectionhash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/size.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbolhash.Po@am__quote@ @@ -617,45 +757,34 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/versionhash.Po@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .l.c: - $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) + $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: - $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) + $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -667,15 +796,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -684,6 +809,21 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -735,10 +875,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -826,11 +971,12 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ - clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \ - distclean distclean-compile distclean-generic distclean-tags \ - distdir dvi dvi-am html html-am info info-am install \ - install-am install-binPROGRAMS install-binSCRIPTS install-data \ +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-binSCRIPTS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ @@ -838,7 +984,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS installcheck-am installcheck-binPROGRAMS \ installcheck-binSCRIPTS installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS @@ -857,7 +1003,7 @@ ldscript.h: ldscript.c @NATIVE_LD_FALSE@ $(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \ @NATIVE_LD_FALSE@ $(libelf) $(libeu) \ @NATIVE_LD_FALSE@ -Wl,--version-script,$(srcdir)/libld_elf_i386.map -@NATIVE_LD_FALSE@ $(textrel_check) +@NATIVE_LD_FALSE@ @$(textrel_check) # Special rule to make it possible to define libld_elf_a_SOURCES as we do. # Otherwise make would complain. @@ -883,7 +1029,7 @@ installcheck-binPROGRAMS: $(bin_PROGRAMS) make-debug-archive: $(srcdir)/make-debug-archive.in UNSTRIP=$(bindir)/`echo unstrip | sed '$(transform)'`; \ AR=$(bindir)/`echo ar | sed '$(transform)'`; \ - sed -e "s,@UNSTRIP@,$$UNSTRIP,g" -e "s,@AR@,$$AR,g" \ + sed -e "s,[@]UNSTRIP[@],$$UNSTRIP,g" -e "s,[@]AR[@],$$AR,g" \ -e "s%[@]PACKAGE_NAME[@]%$(PACKAGE_NAME)%g" \ -e "s%[@]PACKAGE_VERSION[@]%$(PACKAGE_VERSION)%g" \ $(srcdir)/make-debug-archive.in > $@.new diff --git a/src/src/addr2line.c b/src/src/addr2line.c index 2fcc1b10..de802941 100644 --- a/src/src/addr2line.c +++ b/src/src/addr2line.c @@ -1,28 +1,20 @@ /* Locate source files and line information for given addresses - Copyright (C) 2005-2010, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2005-2010, 2012, 2013 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -69,9 +61,13 @@ static const struct argp_option options[] = N_("Show absolute file names using compilation directory"), 0 }, { "functions", 'f', NULL, 0, N_("Also show function names"), 0 }, { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 }, + { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 }, { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 }, { "section", 'j', "NAME", 0, N_("Treat addresses as offsets relative to NAME section."), 0 }, + { "inlines", 'i', NULL, 0, + N_("Show all source locations that caused inline expansion of subroutines at the address."), + 0 }, { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, /* Unsupported options. */ @@ -119,9 +115,15 @@ static bool show_functions; /* True if ELF symbol or section info should be shown. */ static bool show_symbols; +/* True if section associated with a symbol address should be shown. */ +static bool show_symbol_sections; + /* If non-null, take address parameters as relative to named section. */ static const char *just_section; +/* True if all inlined subroutines of the current address should be shown. */ +static bool show_inlines; + int main (int argc, char *argv[]) @@ -160,11 +162,15 @@ main (int argc, char *argv[]) char *buf = NULL; size_t len = 0; + ssize_t chars; while (!feof_unlocked (stdin)) { - if (getline (&buf, &len, stdin) < 0) + if ((chars = getline (&buf, &len, stdin)) < 0) break; + if (buf[chars - 1] == '\n') + buf[chars - 1] = '\0'; + result = handle_address (buf, dwfl); } @@ -177,6 +183,7 @@ main (int argc, char *argv[]) while (++remaining < argc); } + dwfl_end (dwfl); return result; } @@ -231,10 +238,19 @@ parse_opt (int key, char *arg, struct argp_state *state) show_symbols = true; break; + case 'x': + show_symbols = true; + show_symbol_sections = true; + break; + case 'j': just_section = arg; break; + case 'i': + show_inlines = true; + break; + default: return ARGP_ERR_UNKNOWN; } @@ -242,6 +258,23 @@ parse_opt (int key, char *arg, struct argp_state *state) } +static const char * +get_diename (Dwarf_Die *die) +{ + Dwarf_Attribute attr; + const char *name; + + name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name, + &attr) + ?: dwarf_attr_integrate (die, DW_AT_linkage_name, + &attr)); + + if (name == NULL) + name = dwarf_diename (die) ?: "??"; + + return name; +} + static bool print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) { @@ -258,7 +291,7 @@ print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) { case DW_TAG_subprogram: { - const char *name = dwarf_diename (&scopes[i]); + const char *name = get_diename (&scopes[i]); if (name == NULL) return false; puts (name); @@ -267,7 +300,7 @@ print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) case DW_TAG_inlined_subroutine: { - const char *name = dwarf_diename (&scopes[i]); + const char *name = get_diename (&scopes[i]); if (name == NULL) return false; printf ("%s inlined", name); @@ -335,8 +368,9 @@ static void print_addrsym (Dwfl_Module *mod, GElf_Addr addr) { GElf_Sym s; - GElf_Word shndx; - const char *name = dwfl_module_addrsym (mod, addr, &s, &shndx); + GElf_Off off; + const char *name = dwfl_module_addrinfo (mod, addr, &off, &s, + NULL, NULL, NULL); if (name == NULL) { /* No symbol name. Get a section name instead. */ @@ -348,10 +382,34 @@ print_addrsym (Dwfl_Module *mod, GElf_Addr addr) else printf ("(%s)+%#" PRIx64 "\n", name, addr); } - else if (addr == s.st_value) - puts (name); else - printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value); + { + if (off == 0) + printf ("%s", name); + else + printf ("%s+%#" PRIx64 "", name, off); + + // Also show section name for address. + if (show_symbol_sections) + { + Dwarf_Addr ebias; + Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias); + if (scn != NULL) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr != NULL) + { + Elf *elf = dwfl_module_getelf (mod, &ebias); + GElf_Ehdr ehdr; + if (gelf_getehdr (elf, &ehdr) != NULL) + printf (" (%s)", elf_strptr (elf, ehdr.e_shstrndx, + shdr->sh_name)); + } + } + } + puts (""); + } } static int @@ -377,11 +435,14 @@ find_symbol (Dwfl_Module *mod, { const char *looking_for = ((void **) arg)[0]; GElf_Sym *symbol = ((void **) arg)[1]; + GElf_Addr *value = ((void **) arg)[2]; int n = dwfl_module_getsymtab (mod); for (int i = 1; i < n; ++i) { - const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL); + const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol, + value, NULL, NULL, + NULL); if (symbol_name == NULL || symbol_name[0] == '\0') continue; switch (GELF_ST_TYPE (symbol->st_info)) @@ -445,6 +506,30 @@ adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl) return false; } +static void +print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu) +{ + const char *comp_dir = ""; + const char *comp_dir_sep = ""; + + if (only_basenames) + src = basename (src); + else if (use_comp_dir && src[0] != '/') + { + Dwarf_Attribute attr; + comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr)); + if (comp_dir != NULL) + comp_dir_sep = "/"; + } + + if (linecol != 0) + printf ("%s%s%s:%d:%d", + comp_dir, comp_dir_sep, src, lineno, linecol); + else + printf ("%s%s%s:%d", + comp_dir, comp_dir_sep, src, lineno); +} + static int handle_address (const char *string, Dwfl *dwfl) { @@ -471,7 +556,8 @@ handle_address (const char *string, Dwfl *dwfl) /* It was symbol[+offset]. */ GElf_Sym sym; - void *arg[2] = { name, &sym }; + GElf_Addr value = 0; + void *arg[3] = { name, &sym, &value }; (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0); if (arg[0] != NULL) error (0, 0, gettext ("cannot find symbol '%s'"), name); @@ -482,7 +568,7 @@ handle_address (const char *string, Dwfl *dwfl) gettext ("offset %#" PRIxMAX " lies outside" " contents of '%s'"), addr, name); - addr += sym.st_value; + addr += value; parsed = true; } break; @@ -513,28 +599,11 @@ handle_address (const char *string, Dwfl *dwfl) const char *src; int lineno, linecol; + if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, NULL, NULL)) != NULL) { - const char *comp_dir = ""; - const char *comp_dir_sep = ""; - - if (only_basenames) - src = basename (src); - else if (use_comp_dir && src[0] != '/') - { - comp_dir = dwfl_line_comp_dir (line); - if (comp_dir != NULL) - comp_dir_sep = "/"; - } - - if (linecol != 0) - printf ("%s%s%s:%d:%d", - comp_dir, comp_dir_sep, src, lineno, linecol); - else - printf ("%s%s%s:%d", - comp_dir, comp_dir_sep, src, lineno); - + print_src (src, lineno, linecol, dwfl_linecu (line)); if (show_flags) { Dwarf_Addr bias; @@ -568,6 +637,88 @@ handle_address (const char *string, Dwfl *dwfl) else puts ("??:0"); + if (show_inlines) + { + Dwarf_Addr bias = 0; + Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias); + + Dwarf_Die *scopes = NULL; + int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes); + if (nscopes < 0) + return 1; + + if (nscopes > 0) + { + Dwarf_Die subroutine; + Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]); + dwarf_offdie (dwfl_module_getdwarf (mod, &bias), + dieoff, &subroutine); + free (scopes); + + nscopes = dwarf_getscopes_die (&subroutine, &scopes); + if (nscopes > 1) + { + Dwarf_Die cu; + Dwarf_Files *files; + if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL + && dwarf_getsrcfiles (cudie, &files, NULL) == 0) + { + for (int i = 0; i < nscopes - 1; i++) + { + Dwarf_Word val; + Dwarf_Attribute attr; + Dwarf_Die *die = &scopes[i]; + if (dwarf_tag (die) != DW_TAG_inlined_subroutine) + continue; + + if (show_functions) + { + /* Search for the parent inline or function. It + might not be directly above this inline -- e.g. + there could be a lexical_block in between. */ + for (int j = i + 1; j < nscopes; j++) + { + Dwarf_Die *parent = &scopes[j]; + int tag = dwarf_tag (parent); + if (tag == DW_TAG_inlined_subroutine + || tag == DW_TAG_entry_point + || tag == DW_TAG_subprogram) + { + puts (get_diename (parent)); + break; + } + } + } + + src = NULL; + lineno = 0; + linecol = 0; + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, + &attr), &val) == 0) + src = dwarf_filesrc (files, val, NULL, NULL); + + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line, + &attr), &val) == 0) + lineno = val; + + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column, + &attr), &val) == 0) + linecol = val; + + if (src != NULL) + { + print_src (src, lineno, linecol, &cu); + putchar ('\n'); + } + else + puts ("??:0"); + } + } + } + } + free (scopes); + } + return 0; } diff --git a/src/src/ar.c b/src/src/ar.c index 721f4c34..f51f0efd 100644 --- a/src/src/ar.c +++ b/src/src/ar.c @@ -1,27 +1,20 @@ /* Create, modify, and extract from archives. Copyright (C) 2005-2012 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -209,7 +202,7 @@ MEMBER parameter required for 'a', 'b', and 'i' modifiers")); if (instance_specifed) { /* Only valid for certain operations. */ - if (operation == oper_extract && operation == oper_delete) + if (operation != oper_extract && operation != oper_delete) error (1, 0, gettext ("\ 'N' is only meaningful with the 'x' and 'd' options")); @@ -926,7 +919,7 @@ do_oper_delete (const char *arfname, char **argv, int argc, long int instance) { bool *found = alloca (sizeof (bool) * argc); - memset (found, '\0', sizeof (found)); + memset (found, '\0', sizeof (bool) * argc); /* List of the files we keep. */ struct armem *to_copy = NULL; diff --git a/src/src/arlib-argp.c b/src/src/arlib-argp.c index a0e669cf..1bdd8d0b 100644 --- a/src/src/arlib-argp.c +++ b/src/src/arlib-argp.c @@ -1,26 +1,19 @@ /* Options common to ar and ranlib. Copyright (C) 2012 Red Hat, Inc. + This file is part of elfutils. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/arlib.c b/src/src/arlib.c index bcf9344b..43a9145b 100644 --- a/src/src/arlib.c +++ b/src/src/arlib.c @@ -1,27 +1,20 @@ /* Functions to handle creation of Linux archives. Copyright (C) 2007-2012 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -66,11 +59,11 @@ arlib_init (void) _FORTIFY_SOURCE=2 would not let us play these games. Therefore we play it safe. */ char tmpbuf[sizeof (ar_hdr.ar_date) + 1]; - memcpy (ar_hdr.ar_date, tmpbuf, - snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld", + int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld", (int) sizeof (ar_hdr.ar_date), (arlib_deterministic_output ? 0 - : (long long int) time (NULL)))); + : (long long int) time (NULL))); + memcpy (ar_hdr.ar_date, tmpbuf, s); assert ((sizeof (struct ar_hdr) % sizeof (uint32_t)) == 0); /* Note the string for the ar_uid and ar_gid cases is longer than @@ -128,10 +121,10 @@ arlib_finalize (void) symtab.longnames = obstack_finish (&symtab.longnamesob); - memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, - snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu", + int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu", (int) sizeof (((struct ar_hdr *) NULL)->ar_size), - symtab.longnameslen - sizeof (struct ar_hdr))); + symtab.longnameslen - sizeof (struct ar_hdr)); + memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, s); } symtab.symsofflen = obstack_object_size (&symtab.symsoffob); diff --git a/src/src/arlib.h b/src/src/arlib.h index ea77b23e..e117166e 100644 --- a/src/src/arlib.h +++ b/src/src/arlib.h @@ -1,26 +1,19 @@ /* Copyright (C) 2007-2012 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _ARLIB_H #define _ARLIB_H 1 diff --git a/src/src/arlib2.c b/src/src/arlib2.c index 7098fec1..7998fc6c 100644 --- a/src/src/arlib2.c +++ b/src/src/arlib2.c @@ -1,27 +1,20 @@ /* Functions to handle creation of Linux archives. Copyright (C) 2007 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/debugpred.h b/src/src/debugpred.h index 41d46796..4845a6e2 100644 --- a/src/src/debugpred.h +++ b/src/src/debugpred.h @@ -1,28 +1,20 @@ /* Support to debug branch prediction. Copyright (C) 2007 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> diff --git a/src/src/elfcmp.c b/src/src/elfcmp.c index 99296d19..d1008b3c 100644 --- a/src/src/elfcmp.c +++ b/src/src/elfcmp.c @@ -1,28 +1,20 @@ /* Compare relevant content of two ELF files. - Copyright (C) 2005-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2005-2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -363,7 +355,8 @@ main (int argc, char *argv[]) sym1->st_name); const char *name2 = elf_strptr (elf2, shdr2->sh_link, sym2->st_name); - if (unlikely (strcmp (name1, name2) != 0 + if (unlikely (name1 == NULL || name2 == NULL + || strcmp (name1, name2) != 0 || sym1->st_value != sym2->st_value || (sym1->st_size != sym2->st_size && sym1->st_shndx != SHN_UNDEF) @@ -818,8 +811,7 @@ compare_Elf32_Word (const void *p1, const void *p2) { const Elf32_Word *w1 = p1; const Elf32_Word *w2 = p2; - assert (sizeof (int) >= sizeof (*w1)); - return (int) *w1 - (int) *w2; + return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0; } static int diff --git a/src/src/elflint.c b/src/src/elflint.c index abca8b75..7e732531 100644 --- a/src/src/elflint.c +++ b/src/src/elflint.c @@ -1,28 +1,20 @@ /* Pedantic checking of ELF files compliance with gABI/psABI spec. - Copyright (C) 2001-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2001-2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -131,6 +123,10 @@ static uint32_t shstrndx; /* Array to count references in section groups. */ static int *scnref; +/* Numbers of sections and program headers. */ +static unsigned int shnum; +static unsigned int phnum; + int main (int argc, char *argv[]) @@ -319,10 +315,19 @@ section_name (Ebl *ebl, int idx) { GElf_Shdr shdr_mem; GElf_Shdr *shdr; + const char *ret; + + if ((unsigned int) idx > shnum) + return "<invalid>"; shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem); + if (shdr == NULL) + return "<invalid>"; - return elf_strptr (ebl->elf, shstrndx, shdr->sh_name); + ret = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); + if (ret == NULL) + return "<invalid>"; + return ret; } @@ -338,17 +343,13 @@ static const int valid_e_machine[] = EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX, EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM, EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300, - EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA + EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA, + EM_TILEGX, EM_TILEPRO, EM_AARCH64 }; #define nvalid_e_machine \ (sizeof (valid_e_machine) / sizeof (valid_e_machine[0])) -/* Numbers of sections and program headers. */ -static unsigned int shnum; -static unsigned int phnum; - - static void check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size) { @@ -632,7 +633,8 @@ section [%2d] '%s': symbol table cannot have more than one extended index sectio } } - if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)) + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT); + if (shdr->sh_entsize != sh_entsize) ERROR (gettext ("\ section [%2u] '%s': entry size is does not match ElfXX_Sym\n"), idx, section_name (ebl, idx)); @@ -670,7 +672,7 @@ section [%2d] '%s': XINDEX for zeroth entry not zero\n"), xndxscnidx, section_name (ebl, xndxscnidx)); } - for (size_t cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (size_t cnt = 1; cnt < shdr->sh_size / sh_entsize; ++cnt) { sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx); if (sym == NULL) @@ -690,7 +692,8 @@ section [%2d] '%s': symbol %zu: invalid name value\n"), else { name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name); - assert (name != NULL); + assert (name != NULL + || strshdr->sh_type != SHT_STRTAB); } if (sym->st_shndx == SHN_XINDEX) @@ -765,29 +768,44 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"), { GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0 : destshdr->sh_addr); + GElf_Addr st_value; + if (GELF_ST_TYPE (sym->st_info) == STT_FUNC + || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)) + st_value = sym->st_value & ebl_func_addr_mask (ebl); + else + st_value = sym->st_value; if (GELF_ST_TYPE (sym->st_info) != STT_TLS) { if (! ebl_check_special_symbol (ebl, ehdr, sym, name, destshdr)) { - if (sym->st_value - sh_addr > destshdr->sh_size) + if (st_value - sh_addr > destshdr->sh_size) { /* GNU ld has severe bugs. When it decides to remove empty sections it leaves symbols referencing them - behind. These are symbols in .symtab. */ + behind. These are symbols in .symtab or .dynsym + and for the named symbols have zero size. See + sourceware PR13621. */ if (!gnuld - || strcmp (section_name (ebl, idx), ".symtab") + || (strcmp (section_name (ebl, idx), ".symtab") + && strcmp (section_name (ebl, idx), + ".dynsym")) + || sym->st_size != 0 || (strcmp (name, "__preinit_array_start") != 0 && strcmp (name, "__preinit_array_end") != 0 && strcmp (name, "__init_array_start") != 0 && strcmp (name, "__init_array_end") != 0 && strcmp (name, "__fini_array_start") != 0 - && strcmp (name, "__fini_array_end") != 0)) + && strcmp (name, "__fini_array_end") != 0 + && strcmp (name, "__bss_start") != 0 + && strcmp (name, "__bss_start__") != 0 + && strcmp (name, "__TMC_END__") != 0 + && strcmp (name, ".TOC.") != 0)) ERROR (gettext ("\ section [%2d] '%s': symbol %zu: st_value out of bounds\n"), idx, section_name (ebl, idx), cnt); } - else if ((sym->st_value - sh_addr + else if ((st_value - sh_addr + sym->st_size) > destshdr->sh_size) ERROR (gettext ("\ section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), @@ -807,12 +825,12 @@ section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_ { /* For object files the symbol value must fall into the section. */ - if (sym->st_value > destshdr->sh_size) + if (st_value > destshdr->sh_size) ERROR (gettext ("\ section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), idx, section_name (ebl, idx), cnt, (int) xndx, section_name (ebl, xndx)); - else if (sym->st_value + sym->st_size + else if (st_value + sym->st_size > destshdr->sh_size) ERROR (gettext ("\ section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), @@ -841,20 +859,20 @@ section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"), } else { - if (sym->st_value + if (st_value < destshdr->sh_offset - phdr->p_offset) ERROR (gettext ("\ section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"), idx, section_name (ebl, idx), cnt, (int) xndx, section_name (ebl, xndx)); - else if (sym->st_value + else if (st_value > (destshdr->sh_offset - phdr->p_offset + destshdr->sh_size)) ERROR (gettext ("\ section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"), idx, section_name (ebl, idx), cnt, (int) xndx, section_name (ebl, xndx)); - else if (sym->st_value + sym->st_size + else if (st_value + sym->st_size > (destshdr->sh_offset - phdr->p_offset + destshdr->sh_size)) ERROR (gettext ("\ @@ -1039,9 +1057,11 @@ is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr, { GElf_Shdr rcshdr_mem; const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem); - assert (rcshdr != NULL); - if (rcshdr->sh_type == SHT_DYNAMIC) + if (rcshdr == NULL) + break; + + if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize) { /* Found the dynamic section. Look through it. */ Elf_Data *d = elf_getdata (scn, NULL); @@ -1051,7 +1071,9 @@ is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr, { GElf_Dyn dyn_mem; GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem); - assert (dyn != NULL); + + if (dyn == NULL) + break; if (dyn->d_tag == DT_RELCOUNT) { @@ -1065,7 +1087,9 @@ section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"), /* Does the number specified number of relative relocations exceed the total number of relocations? */ - if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize) + if (shdr->sh_entsize != 0 + && dyn->d_un.d_val > (shdr->sh_size + / shdr->sh_entsize)) ERROR (gettext ("\ section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"), idx, section_name (ebl, idx), @@ -1199,8 +1223,7 @@ check_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr, destshdr_memp); if (*destshdrp != NULL) { - if((*destshdrp)->sh_type != SHT_PROGBITS - && (*destshdrp)->sh_type != SHT_NOBITS) + if(! ebl_check_reloc_target_type (ebl, (*destshdrp)->sh_type)) { reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true); if (!reldyn) @@ -1225,7 +1248,8 @@ section [%2d] '%s': no relocations for merge-able sections possible\n"), } } - if (shdr->sh_entsize != gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT)) + size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT); + if (shdr->sh_entsize != sh_entsize) ERROR (gettext (reltype == ELF_T_RELA ? "\ section [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\ section [%2d] '%s': section entry size does not match ElfXX_Rel\n"), @@ -1448,7 +1472,8 @@ check_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) Elf_Data *symdata = elf_getdata (symscn, NULL); enum load_state state = state_undecided; - for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT); + for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { GElf_Rela rela_mem; GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem); @@ -1498,7 +1523,8 @@ check_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) Elf_Data *symdata = elf_getdata (symscn, NULL); enum load_state state = state_undecided; - for (size_t cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT); + for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { GElf_Rel rel_mem; GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem); @@ -1597,7 +1623,8 @@ section [%2d] '%s': referenced as string table for section [%2d] '%s' but type i shdr->sh_link, section_name (ebl, shdr->sh_link), idx, section_name (ebl, idx)); - if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT)) + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT); + if (shdr->sh_entsize != sh_entsize) ERROR (gettext ("\ section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"), idx, section_name (ebl, idx)); @@ -1607,7 +1634,7 @@ section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"), idx, section_name (ebl, idx)); bool non_null_warned = false; - for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { GElf_Dyn dyn_mem; GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem); @@ -1879,6 +1906,8 @@ section [%2d] '%s': entry size does not match Elf32_Word\n"), idx, section_name (ebl, idx)); if (symshdr != NULL + && shdr->sh_entsize + && symshdr->sh_entsize && (shdr->sh_size / shdr->sh_entsize < symshdr->sh_size / symshdr->sh_entsize)) ERROR (gettext ("\ @@ -1905,6 +1934,12 @@ section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same } Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL); + if (data == NULL) + { + ERROR (gettext ("section [%2d] '%s': cannot get section data\n"), + idx, section_name (ebl, idx)); + return; + } if (*((Elf32_Word *) data->d_buf) != 0) ERROR (gettext ("symbol 0 should have zero extended section index\n")); @@ -1947,7 +1982,7 @@ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), size_t maxidx = nchain; - if (symshdr != NULL) + if (symshdr != NULL && symshdr->sh_entsize != 0) { size_t symsize = symshdr->sh_size / symshdr->sh_entsize; @@ -1958,18 +1993,28 @@ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), maxidx = symsize; } + Elf32_Word *buf = (Elf32_Word *) data->d_buf; + Elf32_Word *end = (Elf32_Word *) ((char *) data->d_buf + shdr->sh_size); size_t cnt; for (cnt = 2; cnt < 2 + nbucket; ++cnt) - if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) + { + if (buf + cnt >= end) + break; + else if (buf[cnt] >= maxidx) ERROR (gettext ("\ section [%2d] '%s': hash bucket reference %zu out of bounds\n"), idx, section_name (ebl, idx), cnt - 2); + } for (; cnt < 2 + nbucket + nchain; ++cnt) - if (((Elf32_Word *) data->d_buf)[cnt] >= maxidx) + { + if (buf + cnt >= end) + break; + else if (buf[cnt] >= maxidx) ERROR (gettext ("\ section [%2d] '%s': hash chain reference %zu out of bounds\n"), idx, section_name (ebl, idx), cnt - 2 - nbucket); + } } @@ -1999,18 +2044,28 @@ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), maxidx = symsize; } + Elf64_Xword *buf = (Elf64_Xword *) data->d_buf; + Elf64_Xword *end = (Elf64_Xword *) ((char *) data->d_buf + shdr->sh_size); size_t cnt; for (cnt = 2; cnt < 2 + nbucket; ++cnt) - if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) + { + if (buf + cnt >= end) + break; + else if (buf[cnt] >= maxidx) ERROR (gettext ("\ section [%2d] '%s': hash bucket reference %zu out of bounds\n"), idx, section_name (ebl, idx), cnt - 2); + } for (; cnt < 2 + nbucket + nchain; ++cnt) - if (((Elf64_Xword *) data->d_buf)[cnt] >= maxidx) + { + if (buf + cnt >= end) + break; + else if (buf[cnt] >= maxidx) ERROR (gettext ("\ section [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"), - idx, section_name (ebl, idx), (uint64_t) (cnt - 2 - nbucket)); + idx, section_name (ebl, idx), (uint64_t) cnt - 2 - nbucket); + } } @@ -2035,7 +2090,7 @@ section [%2d] '%s': bitmask size not power of 2: %u\n"), if (shdr->sh_size < (4 + bitmask_words + nbuckets) * sizeof (Elf32_Word)) { ERROR (gettext ("\ -section [%2d] '%s': hash table section is too small (is %ld, expected at least%ld)\n"), +section [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"), idx, section_name (ebl, idx), (long int) shdr->sh_size, (long int) ((4 + bitmask_words + nbuckets) * sizeof (Elf32_Word))); return; @@ -2707,8 +2762,9 @@ section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic s /* The number of elements in the version symbol table must be the same as the number of symbols. */ - if (shdr->sh_size / shdr->sh_entsize - != symshdr->sh_size / symshdr->sh_entsize) + if (shdr->sh_entsize && symshdr->sh_entsize + && (shdr->sh_size / shdr->sh_entsize + != symshdr->sh_size / symshdr->sh_entsize)) ERROR (gettext ("\ section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"), idx, section_name (ebl, idx), @@ -3210,7 +3266,7 @@ section [%2d] '%s': offset %zu: unterminated vendor name string\n"), unsigned const char *chunk = q; unsigned int subsection_tag; - get_uleb128 (subsection_tag, q); + get_uleb128 (subsection_tag, q, p); if (q >= p) { @@ -3265,13 +3321,13 @@ section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"), while (chunk < q) { unsigned int tag; - get_uleb128 (tag, chunk); + get_uleb128 (tag, chunk, q); uint64_t value = 0; const unsigned char *r = chunk; if (tag == 32 || (tag & 1) == 0) { - get_uleb128 (value, r); + get_uleb128 (value, r, q); if (r > q) { ERROR (gettext ("\ @@ -3357,8 +3413,8 @@ static const struct { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC }, { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 }, - { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests - { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests + { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests + { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS }, { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 }, @@ -3476,7 +3532,7 @@ cannot get section header for section [%2zu] '%s': %s\n"), GElf_Word good_type = special_sections[s].type; if (IS_KNOWN_SPECIAL (s, ".plt", false) - && ebl_bss_plt_p (ebl, ehdr)) + && ebl_bss_plt_p (ebl)) good_type = SHT_NOBITS; /* In a debuginfo file, any normal section can be SHT_NOBITS. @@ -3716,8 +3772,10 @@ section [%2zu] '%s' is both executable and writable\n"), || (phdr->p_type == PT_TLS && (shdr->sh_flags & SHF_TLS) != 0)) && phdr->p_offset <= shdr->sh_offset - && (phdr->p_offset + phdr->p_filesz > shdr->sh_offset - || (phdr->p_offset + phdr->p_memsz > shdr->sh_offset + && ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz + && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz + || shdr->sh_size == 0)) + || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz && shdr->sh_type == SHT_NOBITS))) { /* Found the segment. */ diff --git a/src/src/findtextrel.c b/src/src/findtextrel.c index 444f3a2b..264a06bd 100644 --- a/src/src/findtextrel.c +++ b/src/src/findtextrel.c @@ -1,28 +1,20 @@ /* Locate source files or functions which caused text relocations. - Copyright (C) 2005-2010, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2005-2010, 2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -319,7 +311,7 @@ process_file (const char *fname, bool more_than_one) if (!have_textrel) { error (0, 0, gettext ("no text relocations reported in '%s'"), fname); - return 1; + goto err_elf_close; } int fd2 = -1; @@ -332,14 +324,20 @@ process_file (const char *fname, bool more_than_one) if (segments == NULL) error (1, errno, gettext ("while reading ELF file")); - for (int i = 0; i < ehdr->e_phnum; ++i) + size_t phnum; + if (elf_getphdrnum (elf, &phnum) != 0) + error (1, 0, gettext ("cannot get program header count: %s"), + elf_errmsg (-1)); + + + for (size_t i = 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); if (phdr == NULL) { error (0, 0, - gettext ("cannot get program header index at offset %d: %s"), + gettext ("cannot get program header index at offset %zd: %s"), i, elf_errmsg (-1)); result = 1; goto next; @@ -357,7 +355,7 @@ process_file (const char *fname, bool more_than_one) if (segments == NULL) { error (0, 0, gettext ("\ -cannot get program header index at offset %d: %s"), +cannot get program header index at offset %zd: %s"), i, elf_errmsg (-1)); result = 1; goto next; diff --git a/src/src/i386_ld.c b/src/src/i386_ld.c index 2702ef85..d196177a 100644 --- a/src/src/i386_ld.c +++ b/src/src/i386_ld.c @@ -1,27 +1,19 @@ /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/ld.c b/src/src/ld.c index 6384e86a..73e4f04f 100644 --- a/src/src/ld.c +++ b/src/src/ld.c @@ -1,27 +1,19 @@ /* Copyright (C) 2001-2010, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/ld.h b/src/src/ld.h index 72d5b27b..29f4031b 100644 --- a/src/src/ld.h +++ b/src/src/ld.h @@ -1,27 +1,19 @@ /* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2008, 2009 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef LD_H #define LD_H 1 diff --git a/src/src/ldgeneric.c b/src/src/ldgeneric.c index 98bdc225..1b5d0f9b 100644 --- a/src/src/ldgeneric.c +++ b/src/src/ldgeneric.c @@ -1,27 +1,19 @@ /* Copyright (C) 2001-2011 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/ldlex.c b/src/src/ldlex.c index e1b5b4e9..03870df0 100644 --- a/src/src/ldlex.c +++ b/src/src/ldlex.c @@ -28,7 +28,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 35 +#define YY_FLEX_SUBMINOR_VERSION 37 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -73,7 +73,6 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -104,6 +103,8 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif +#endif /* ! C99 */ + #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -172,7 +173,12 @@ typedef unsigned int flex_uint32_t; typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif -extern int ldleng; +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t ldleng; extern FILE *ldin, *ldout; @@ -211,11 +217,6 @@ extern FILE *ldin, *ldout; #define unput(c) yyunput( c, (yytext_ptr) ) -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif - #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state @@ -233,7 +234,7 @@ struct yy_buffer_state /* Number of characters read into yy_ch_buf, not including EOB * characters. */ - int yy_n_chars; + yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to @@ -303,8 +304,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* yy_hold_char holds the character lost when ldtext is formed. */ static char yy_hold_char; -static int yy_n_chars; /* number of characters read into yy_ch_buf */ -int ldleng; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t ldleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; @@ -332,7 +333,7 @@ static void ld_init_buffer (YY_BUFFER_STATE b,FILE *file ); YY_BUFFER_STATE ld_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE ld_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE ld_scan_bytes (yyconst char *bytes,int len ); +YY_BUFFER_STATE ld_scan_bytes (yyconst char *bytes,yy_size_t len ); void *ldalloc (yy_size_t ); void *ldrealloc (void *,yy_size_t ); @@ -364,7 +365,7 @@ void ldfree (void * ); /* Begin user sect3 */ -#define ldwrap(n) 1 +#define ldwrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -1072,32 +1073,24 @@ int ld_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *ldtext; -#line 1 "ldlex.l" -#line 2 "ldlex.l" +#line 1 "/home/mark/src/elfutils/src/ldlex.l" +#line 2 "/home/mark/src/elfutils/src/ldlex.l" /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -1153,7 +1146,7 @@ static int pop_state (void); static int handle_ifdef (void); static void invalid_char (int ch); -#line 1157 "ldlex.c" +#line 1150 "ldlex.c" #define INITIAL 0 #define IGNORE 1 @@ -1193,7 +1186,7 @@ FILE *ldget_out (void ); void ldset_out (FILE * out_str ); -int ldget_leng (void ); +yy_size_t ldget_leng (void ); char *ldget_text (void ); @@ -1254,7 +1247,7 @@ static int input (void ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - unsigned n; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( ldin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -1339,7 +1332,7 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 96 "ldlex.l" +#line 88 "/home/mark/src/elfutils/src/ldlex.l" if (unlikely (ld_scan_version_script)) { @@ -1347,7 +1340,7 @@ YY_DECL return kVERSION_SCRIPT; } -#line 1351 "ldlex.c" +#line 1344 "ldlex.c" if ( !(yy_init) ) { @@ -1418,7 +1411,7 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { - int yyl; + yy_size_t yyl; for ( yyl = 0; yyl < ldleng; ++yyl ) if ( ldtext[yyl] == '\n' ) @@ -1443,7 +1436,7 @@ case 1: (yy_c_buf_p) = yy_cp = yy_bp + 6; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 103 "ldlex.l" +#line 95 "/home/mark/src/elfutils/src/ldlex.l" { BEGIN (handle_ifdef ()); } YY_BREAK case 2: @@ -1452,7 +1445,7 @@ case 2: (yy_c_buf_p) = yy_cp = yy_bp + 5; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 104 "ldlex.l" +#line 96 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (true); push_state (skip_to_endif); BEGIN (IGNORE); } @@ -1463,7 +1456,7 @@ case 3: (yy_c_buf_p) = yy_cp = yy_bp + 8; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 107 "ldlex.l" +#line 99 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (false); push_state (skip_to_endif); BEGIN (IGNORE); } @@ -1474,7 +1467,7 @@ case 4: (yy_c_buf_p) = yy_cp = yy_bp + 6; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 110 "ldlex.l" +#line 102 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (true) ; } YY_BREAK case 5: @@ -1483,7 +1476,7 @@ case 5: (yy_c_buf_p) = yy_cp = yy_bp + 6; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 112 "ldlex.l" +#line 104 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (false); push_state (skip_to_endif); } YY_BREAK @@ -1493,7 +1486,7 @@ case 6: (yy_c_buf_p) = yy_cp = yy_bp + 5; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 114 "ldlex.l" +#line 106 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (true); assert (prepdepth > 0); if (prepstate[prepdepth - 1] == skip_if) @@ -1510,7 +1503,7 @@ case 7: (yy_c_buf_p) = yy_cp = yy_bp + 8; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 123 "ldlex.l" +#line 115 "/home/mark/src/elfutils/src/ldlex.l" { assert (prepdepth > 0); if (prepstate[prepdepth - 1] == skip_if) { @@ -1526,114 +1519,114 @@ case 8: (yy_c_buf_p) = yy_cp = yy_bp + 6; YY_DO_BEFORE_ACTION; /* set up ldtext again */ YY_RULE_SETUP -#line 131 "ldlex.l" +#line 123 "/home/mark/src/elfutils/src/ldlex.l" { eat_to_eol (true); BEGIN (pop_state ()); } YY_BREAK case 9: /* rule 9 can match eol */ YY_RULE_SETUP -#line 133 "ldlex.l" +#line 125 "/home/mark/src/elfutils/src/ldlex.l" { /* nothing */ } YY_BREAK case 10: YY_RULE_SETUP -#line 136 "ldlex.l" +#line 128 "/home/mark/src/elfutils/src/ldlex.l" { eat_comment (); } YY_BREAK case 11: YY_RULE_SETUP -#line 138 "ldlex.l" +#line 130 "/home/mark/src/elfutils/src/ldlex.l" { return kALIGN; } YY_BREAK case 12: YY_RULE_SETUP -#line 139 "ldlex.l" +#line 131 "/home/mark/src/elfutils/src/ldlex.l" { return kAS_NEEDED; } YY_BREAK case 13: YY_RULE_SETUP -#line 140 "ldlex.l" +#line 132 "/home/mark/src/elfutils/src/ldlex.l" { return kENTRY; } YY_BREAK case 14: YY_RULE_SETUP -#line 141 "ldlex.l" +#line 133 "/home/mark/src/elfutils/src/ldlex.l" { return kEXCLUDE_FILE; } YY_BREAK case 15: YY_RULE_SETUP -#line 142 "ldlex.l" +#line 134 "/home/mark/src/elfutils/src/ldlex.l" { return kGLOBAL; } YY_BREAK case 16: YY_RULE_SETUP -#line 143 "ldlex.l" +#line 135 "/home/mark/src/elfutils/src/ldlex.l" { return kGROUP; } YY_BREAK case 17: YY_RULE_SETUP -#line 144 "ldlex.l" +#line 136 "/home/mark/src/elfutils/src/ldlex.l" { return kINPUT; } YY_BREAK case 18: YY_RULE_SETUP -#line 145 "ldlex.l" +#line 137 "/home/mark/src/elfutils/src/ldlex.l" { return kINTERP; } YY_BREAK case 19: YY_RULE_SETUP -#line 146 "ldlex.l" +#line 138 "/home/mark/src/elfutils/src/ldlex.l" { return kKEEP; } YY_BREAK case 20: YY_RULE_SETUP -#line 147 "ldlex.l" +#line 139 "/home/mark/src/elfutils/src/ldlex.l" { return kLOCAL; } YY_BREAK case 21: YY_RULE_SETUP -#line 148 "ldlex.l" +#line 140 "/home/mark/src/elfutils/src/ldlex.l" { return kOUTPUT_FORMAT; } YY_BREAK case 22: YY_RULE_SETUP -#line 149 "ldlex.l" +#line 141 "/home/mark/src/elfutils/src/ldlex.l" { return kPAGESIZE; } YY_BREAK case 23: YY_RULE_SETUP -#line 150 "ldlex.l" +#line 142 "/home/mark/src/elfutils/src/ldlex.l" { return kPROVIDE; } YY_BREAK case 24: YY_RULE_SETUP -#line 151 "ldlex.l" +#line 143 "/home/mark/src/elfutils/src/ldlex.l" { return kSEARCH_DIR; } YY_BREAK case 25: YY_RULE_SETUP -#line 152 "ldlex.l" +#line 144 "/home/mark/src/elfutils/src/ldlex.l" { return kSEGMENT; } YY_BREAK case 26: YY_RULE_SETUP -#line 153 "ldlex.l" +#line 145 "/home/mark/src/elfutils/src/ldlex.l" { return kSIZEOF_HEADERS; } YY_BREAK case 27: YY_RULE_SETUP -#line 154 "ldlex.l" +#line 146 "/home/mark/src/elfutils/src/ldlex.l" { return kSORT; } YY_BREAK case 28: YY_RULE_SETUP -#line 155 "ldlex.l" +#line 147 "/home/mark/src/elfutils/src/ldlex.l" { return kVERSION; } YY_BREAK case 29: YY_RULE_SETUP -#line 157 "ldlex.l" +#line 149 "/home/mark/src/elfutils/src/ldlex.l" { int cnt = 1 ; ldlval.num = 0; while (cnt < ldleng - 1) @@ -1642,82 +1635,82 @@ YY_RULE_SETUP YY_BREAK case 30: YY_RULE_SETUP -#line 163 "ldlex.l" +#line 155 "/home/mark/src/elfutils/src/ldlex.l" { return '{'; } YY_BREAK case 31: YY_RULE_SETUP -#line 164 "ldlex.l" +#line 156 "/home/mark/src/elfutils/src/ldlex.l" { return '}'; } YY_BREAK case 32: YY_RULE_SETUP -#line 165 "ldlex.l" +#line 157 "/home/mark/src/elfutils/src/ldlex.l" { return '('; } YY_BREAK case 33: YY_RULE_SETUP -#line 166 "ldlex.l" +#line 158 "/home/mark/src/elfutils/src/ldlex.l" { return ')'; } YY_BREAK case 34: YY_RULE_SETUP -#line 167 "ldlex.l" +#line 159 "/home/mark/src/elfutils/src/ldlex.l" { return ':'; } YY_BREAK case 35: YY_RULE_SETUP -#line 168 "ldlex.l" +#line 160 "/home/mark/src/elfutils/src/ldlex.l" { return ';'; } YY_BREAK case 36: YY_RULE_SETUP -#line 169 "ldlex.l" +#line 161 "/home/mark/src/elfutils/src/ldlex.l" { return '='; } YY_BREAK case 37: YY_RULE_SETUP -#line 170 "ldlex.l" +#line 162 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.op = exp_plus; return kADD_OP; } YY_BREAK case 38: YY_RULE_SETUP -#line 171 "ldlex.l" +#line 163 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.op = exp_minus; return kADD_OP; } YY_BREAK case 39: YY_RULE_SETUP -#line 172 "ldlex.l" +#line 164 "/home/mark/src/elfutils/src/ldlex.l" { return '*'; } YY_BREAK case 40: YY_RULE_SETUP -#line 173 "ldlex.l" +#line 165 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.op = exp_div; return kMUL_OP; } YY_BREAK case 41: YY_RULE_SETUP -#line 174 "ldlex.l" +#line 166 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.op = exp_mod; return kMUL_OP; } YY_BREAK case 42: YY_RULE_SETUP -#line 175 "ldlex.l" +#line 167 "/home/mark/src/elfutils/src/ldlex.l" { return '&'; } YY_BREAK case 43: YY_RULE_SETUP -#line 176 "ldlex.l" +#line 168 "/home/mark/src/elfutils/src/ldlex.l" { return '|'; } YY_BREAK case 44: YY_RULE_SETUP -#line 178 "ldlex.l" +#line 170 "/home/mark/src/elfutils/src/ldlex.l" { return ','; } YY_BREAK case 45: YY_RULE_SETUP -#line 180 "ldlex.l" +#line 172 "/home/mark/src/elfutils/src/ldlex.l" { char *endp; ldlval.num = strtoumax (ldtext, &endp, 0); if (*endp != '\0') @@ -1734,14 +1727,14 @@ YY_RULE_SETUP YY_BREAK case 46: YY_RULE_SETUP -#line 194 "ldlex.l" +#line 186 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.str = obstack_strndup (&ld_state.smem, ldtext, ldleng); return kID; } YY_BREAK case 47: YY_RULE_SETUP -#line 198 "ldlex.l" +#line 190 "/home/mark/src/elfutils/src/ldlex.l" { ldlval.str = obstack_strndup (&ld_state.smem, ldtext, ldleng); return kFILENAME; } @@ -1749,20 +1742,20 @@ YY_RULE_SETUP case 48: /* rule 48 can match eol */ YY_RULE_SETUP -#line 202 "ldlex.l" +#line 194 "/home/mark/src/elfutils/src/ldlex.l" { /* IGNORE */ } YY_BREAK case 49: YY_RULE_SETUP -#line 204 "ldlex.l" +#line 196 "/home/mark/src/elfutils/src/ldlex.l" { invalid_char (*ldtext); } YY_BREAK case 50: YY_RULE_SETUP -#line 206 "ldlex.l" +#line 198 "/home/mark/src/elfutils/src/ldlex.l" ECHO; YY_BREAK -#line 1766 "ldlex.c" +#line 1759 "ldlex.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(IGNORE): yyterminate(); @@ -1950,21 +1943,21 @@ static int yy_get_next_buffer (void) else { - int num_to_read = + yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { - int new_size = b->yy_buf_size * 2; + yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; @@ -1995,7 +1988,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -2091,7 +2084,7 @@ static int yy_get_next_buffer (void) yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 218); - return yy_is_jam ? 0 : yy_current_state; + return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) @@ -2106,7 +2099,7 @@ static int yy_get_next_buffer (void) if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; + register yy_size_t number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = @@ -2159,7 +2152,7 @@ static int yy_get_next_buffer (void) else { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) @@ -2437,7 +2430,7 @@ void ldpop_buffer_state (void) */ static void ldensure_buffer_stack (void) { - int num_to_alloc; + yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { @@ -2529,17 +2522,17 @@ YY_BUFFER_STATE ld_scan_string (yyconst char * yystr ) /** Setup the input buffer state to scan the given bytes. The next call to ldlex() will * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE ld_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +YY_BUFFER_STATE ld_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; - int i; + yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -2621,7 +2614,7 @@ FILE *ldget_out (void) /** Get the length of the current token. * */ -int ldget_leng (void) +yy_size_t ldget_leng (void) { return ldleng; } @@ -2772,7 +2765,7 @@ void ldfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 206 "ldlex.l" +#line 198 "/home/mark/src/elfutils/src/ldlex.l" diff --git a/src/src/ldlex.l b/src/src/ldlex.l index eb15c7be..bfc8bbe5 100644 --- a/src/src/ldlex.l +++ b/src/src/ldlex.l @@ -1,28 +1,20 @@ %{ /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/ldscript.c b/src/src/ldscript.c index 05a393bb..690d805e 100644 --- a/src/src/ldscript.c +++ b/src/src/ldscript.c @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.7" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,8 +58,6 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse ldparse @@ -70,37 +68,27 @@ #define yydebug lddebug #define yynerrs ldnerrs - /* Copy the first part of user declarations. */ - -/* Line 268 of yacc.c */ -#line 1 "ldscript.y" +/* Line 371 of yacc.c */ +#line 1 "/home/mark/src/elfutils/src/ldscript.y" /* Parser for linker scripts. Copyright (C) 2001-2011 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -144,14 +132,16 @@ static void add_versions (struct version *versions); extern int yylex (void); +/* Line 371 of yacc.c */ +#line 137 "ldscript.c" -/* Line 268 of yacc.c */ -#line 150 "ldscript.c" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -161,11 +151,17 @@ extern int yylex (void); # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "y.tab.h". */ +#ifndef YY_LD_LDSCRIPT_H_INCLUDED +# define YY_LD_LDSCRIPT_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int lddebug; #endif - /* Tokens. */ #ifndef YYTOKENTYPE @@ -233,13 +229,11 @@ extern int yylex (void); - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { - -/* Line 293 of yacc.c */ -#line 71 "ldscript.y" +/* Line 387 of yacc.c */ +#line 63 "/home/mark/src/elfutils/src/ldscript.y" uintmax_t num; enum expression_tag op; @@ -255,21 +249,36 @@ typedef union YYSTYPE struct id_list *id_list; - -/* Line 293 of yacc.c */ -#line 261 "ldscript.c" +/* Line 387 of yacc.c */ +#line 254 "ldscript.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif +extern YYSTYPE ldlval; -/* Copy the second part of user declarations. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int ldparse (void *YYPARSE_PARAM); +#else +int ldparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int ldparse (void); +#else +int ldparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_LD_LDSCRIPT_H_INCLUDED */ -/* Line 343 of yacc.c */ -#line 273 "ldscript.c" +/* Copy the second part of user declarations. */ + +/* Line 390 of yacc.c */ +#line 282 "ldscript.c" #ifdef short # undef short @@ -322,24 +331,24 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -375,6 +384,7 @@ YYID (yyi) # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -466,20 +476,20 @@ union yyalloc #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ while (YYID (0)) # endif # endif @@ -587,17 +597,17 @@ static const yytype_int8 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 143, 143, 144, 148, 149, 152, 157, 161, 166, - 172, 176, 182, 193, 195, 197, 199, 203, 208, 212, - 217, 229, 253, 255, 259, 264, 268, 273, 280, 287, - 298, 300, 304, 307, 310, 315, 317, 323, 329, 335, - 341, 347, 352, 357, 359, 363, 368, 372, 373, 376, - 387, 389, 394, 399, 403, 409, 415, 424, 426, 430, - 432, 437, 443, 447, 449, 453, 455 + 0, 135, 135, 136, 140, 141, 144, 149, 153, 158, + 164, 168, 174, 185, 187, 189, 191, 195, 200, 204, + 209, 221, 245, 247, 251, 256, 260, 265, 272, 279, + 290, 292, 296, 299, 302, 307, 309, 315, 321, 327, + 333, 339, 344, 349, 351, 355, 360, 364, 365, 368, + 379, 381, 386, 391, 395, 401, 407, 416, 418, 422, + 424, 429, 435, 439, 441, 445, 447 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -613,7 +623,7 @@ static const char *const yytname[] = "inputsection", "sectionname", "sort_opt_name", "exclude_opt", "expr", "filename_id_list", "comma_opt", "filename_id_listelem", "versionlist", "version", "version_stmt_list", "version_stmt", "filename_id_star_list", - "filename_id", "filename_id_star", 0 + "filename_id", "filename_id_star", YY_NULL }; #endif @@ -746,10 +756,10 @@ static const yytype_uint8 yytable[] = 0, 0, 0, 0, 81, 0, 78 }; -#define yypact_value_is_default(yystate) \ - ((yystate) == (-86)) +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-86))) -#define yytable_value_is_error(yytable_value) \ +#define yytable_value_is_error(Yytable_value) \ YYID (0) static const yytype_int16 yycheck[] = @@ -828,62 +838,35 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - /* This macro is provided for backward compatibility. */ - #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else @@ -933,6 +916,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) YYSTYPE const * const yyvaluep; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT @@ -944,7 +929,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) switch (yytype) { default: - break; + break; } } @@ -1184,12 +1169,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULL; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1249,11 +1233,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } } } @@ -1273,10 +1259,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, # undef YYCASE_ } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } if (*yymsg_alloc < yysize) { @@ -1336,32 +1324,27 @@ yydestruct (yymsg, yytype, yyvaluep) { default: - break; + break; } } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; + +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1401,7 +1384,7 @@ yyparse () `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1419,7 +1402,7 @@ yyparse () int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1437,9 +1420,8 @@ yyparse () Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1448,14 +1430,6 @@ yyparse () yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1596,7 +1570,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1633,16 +1609,14 @@ yyreduce: switch (yyn) { case 3: - -/* Line 1806 of yacc.c */ -#line 145 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 137 "/home/mark/src/elfutils/src/ldscript.y" { add_versions ((yyvsp[(2) - (2)].version)); } break; case 6: - -/* Line 1806 of yacc.c */ -#line 153 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 145 "/home/mark/src/elfutils/src/ldscript.y" { if (likely (ld_state.entry == NULL)) ld_state.entry = (yyvsp[(3) - (5)].str); @@ -1650,18 +1624,16 @@ yyreduce: break; case 7: - -/* Line 1806 of yacc.c */ -#line 158 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 150 "/home/mark/src/elfutils/src/ldscript.y" { ld_new_searchdir ((yyvsp[(3) - (5)].str)); } break; case 8: - -/* Line 1806 of yacc.c */ -#line 162 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 154 "/home/mark/src/elfutils/src/ldscript.y" { if (likely (ld_state.pagesize == 0)) ld_state.pagesize = (yyvsp[(3) - (5)].num); @@ -1669,9 +1641,8 @@ yyreduce: break; case 9: - -/* Line 1806 of yacc.c */ -#line 167 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 159 "/home/mark/src/elfutils/src/ldscript.y" { if (likely (ld_state.interp == NULL) && ld_state.file_type != dso_file_type) @@ -1680,18 +1651,16 @@ yyreduce: break; case 10: - -/* Line 1806 of yacc.c */ -#line 173 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 165 "/home/mark/src/elfutils/src/ldscript.y" { new_segment ((yyvsp[(2) - (5)].num), (yyvsp[(4) - (5)].output_rule)); } break; case 11: - -/* Line 1806 of yacc.c */ -#line 177 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 169 "/home/mark/src/elfutils/src/ldscript.y" { fputs_unlocked (gettext ("mode for segment invalid\n"), stderr); @@ -1700,9 +1669,8 @@ yyreduce: break; case 12: - -/* Line 1806 of yacc.c */ -#line 183 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 175 "/home/mark/src/elfutils/src/ldscript.y" { /* First little optimization. If there is only one file in the group don't do anything. */ @@ -1716,37 +1684,32 @@ yyreduce: break; case 13: - -/* Line 1806 of yacc.c */ -#line 194 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 186 "/home/mark/src/elfutils/src/ldscript.y" { add_inputfiles ((yyvsp[(3) - (4)].filename_list)); } break; case 14: - -/* Line 1806 of yacc.c */ -#line 196 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 188 "/home/mark/src/elfutils/src/ldscript.y" { add_inputfiles (mark_as_needed ((yyvsp[(3) - (4)].filename_list))); } break; case 15: - -/* Line 1806 of yacc.c */ -#line 198 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 190 "/home/mark/src/elfutils/src/ldscript.y" { add_versions ((yyvsp[(3) - (4)].version)); } break; case 16: - -/* Line 1806 of yacc.c */ -#line 200 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 192 "/home/mark/src/elfutils/src/ldscript.y" { /* XXX TODO */ } break; case 17: - -/* Line 1806 of yacc.c */ -#line 204 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 196 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(2) - (2)].output_rule)->next = (yyvsp[(1) - (2)].output_rule)->next; (yyval.output_rule) = (yyvsp[(1) - (2)].output_rule)->next = (yyvsp[(2) - (2)].output_rule); @@ -1754,16 +1717,14 @@ yyreduce: break; case 18: - -/* Line 1806 of yacc.c */ -#line 209 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 201 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.output_rule) = (yyvsp[(1) - (1)].output_rule); } break; case 19: - -/* Line 1806 of yacc.c */ -#line 213 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 205 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.output_rule) = new_output_rule (output_assignment); (yyval.output_rule)->val.assignment = (yyvsp[(1) - (2)].assignment); @@ -1771,9 +1732,8 @@ yyreduce: break; case 20: - -/* Line 1806 of yacc.c */ -#line 218 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 210 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.output_rule) = new_output_rule (output_section); (yyval.output_rule)->val.section.name = (yyvsp[(1) - (4)].str); @@ -1788,9 +1748,8 @@ yyreduce: break; case 21: - -/* Line 1806 of yacc.c */ -#line 230 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 222 "/home/mark/src/elfutils/src/ldscript.y" { /* This is a short cut for "ID { *(ID) }". */ (yyval.output_rule) = new_output_rule (output_section); @@ -1815,23 +1774,20 @@ yyreduce: break; case 22: - -/* Line 1806 of yacc.c */ -#line 254 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 246 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.assignment) = new_assignment ((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].expr), false); } break; case 23: - -/* Line 1806 of yacc.c */ -#line 256 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 248 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.assignment) = new_assignment ((yyvsp[(3) - (6)].str), (yyvsp[(5) - (6)].expr), true); } break; case 24: - -/* Line 1806 of yacc.c */ -#line 260 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 252 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(2) - (2)].input_rule)->next = (yyvsp[(1) - (2)].input_rule)->next; (yyval.input_rule) = (yyvsp[(1) - (2)].input_rule)->next = (yyvsp[(2) - (2)].input_rule); @@ -1839,16 +1795,14 @@ yyreduce: break; case 25: - -/* Line 1806 of yacc.c */ -#line 265 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 257 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.input_rule) = (yyvsp[(1) - (1)].input_rule); } break; case 26: - -/* Line 1806 of yacc.c */ -#line 269 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 261 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.input_rule) = new_input_rule (input_section); (yyval.input_rule)->val.section = (yyvsp[(1) - (1)].filemask_section_name); @@ -1856,9 +1810,8 @@ yyreduce: break; case 27: - -/* Line 1806 of yacc.c */ -#line 274 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 266 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(3) - (4)].filemask_section_name)->keep_flag = true; @@ -1868,9 +1821,8 @@ yyreduce: break; case 28: - -/* Line 1806 of yacc.c */ -#line 281 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 273 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.input_rule) = new_input_rule (input_assignment); (yyval.input_rule)->val.assignment = (yyvsp[(1) - (2)].assignment); @@ -1878,9 +1830,8 @@ yyreduce: break; case 29: - -/* Line 1806 of yacc.c */ -#line 288 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 280 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.filemask_section_name) = (struct filemask_section_name *) obstack_alloc (&ld_state.smem, sizeof (*(yyval.filemask_section_name))); @@ -1892,37 +1843,32 @@ yyreduce: break; case 30: - -/* Line 1806 of yacc.c */ -#line 299 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 291 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.sectionname) = new_input_section_name ((yyvsp[(1) - (1)].str), false); } break; case 31: - -/* Line 1806 of yacc.c */ -#line 301 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 293 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.sectionname) = new_input_section_name ((yyvsp[(3) - (4)].str), true); } break; case 32: - -/* Line 1806 of yacc.c */ -#line 305 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 297 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = (yyvsp[(3) - (4)].str); } break; case 33: - -/* Line 1806 of yacc.c */ -#line 307 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 299 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = NULL; } break; case 34: - -/* Line 1806 of yacc.c */ -#line 311 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 303 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_align); (yyval.expr)->val.child = (yyvsp[(3) - (4)].expr); @@ -1930,16 +1876,14 @@ yyreduce: break; case 35: - -/* Line 1806 of yacc.c */ -#line 316 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 308 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 36: - -/* Line 1806 of yacc.c */ -#line 318 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 310 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_mult); (yyval.expr)->val.binary.left = (yyvsp[(1) - (3)].expr); @@ -1948,9 +1892,8 @@ yyreduce: break; case 37: - -/* Line 1806 of yacc.c */ -#line 324 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 316 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr ((yyvsp[(2) - (3)].op)); (yyval.expr)->val.binary.left = (yyvsp[(1) - (3)].expr); @@ -1959,9 +1902,8 @@ yyreduce: break; case 38: - -/* Line 1806 of yacc.c */ -#line 330 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 322 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr ((yyvsp[(2) - (3)].op)); (yyval.expr)->val.binary.left = (yyvsp[(1) - (3)].expr); @@ -1970,9 +1912,8 @@ yyreduce: break; case 39: - -/* Line 1806 of yacc.c */ -#line 336 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 328 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_and); (yyval.expr)->val.binary.left = (yyvsp[(1) - (3)].expr); @@ -1981,9 +1922,8 @@ yyreduce: break; case 40: - -/* Line 1806 of yacc.c */ -#line 342 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 334 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_or); (yyval.expr)->val.binary.left = (yyvsp[(1) - (3)].expr); @@ -1992,9 +1932,8 @@ yyreduce: break; case 41: - -/* Line 1806 of yacc.c */ -#line 348 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 340 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_num); (yyval.expr)->val.num = (yyvsp[(1) - (1)].num); @@ -2002,9 +1941,8 @@ yyreduce: break; case 42: - -/* Line 1806 of yacc.c */ -#line 353 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 345 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_id); (yyval.expr)->val.str = (yyvsp[(1) - (1)].str); @@ -2012,23 +1950,20 @@ yyreduce: break; case 43: - -/* Line 1806 of yacc.c */ -#line 358 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 350 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_sizeof_headers); } break; case 44: - -/* Line 1806 of yacc.c */ -#line 360 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 352 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.expr) = new_expr (exp_pagesize); } break; case 45: - -/* Line 1806 of yacc.c */ -#line 364 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 356 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(3) - (3)].filename_list)->next = (yyvsp[(1) - (3)].filename_list)->next; (yyval.filename_list) = (yyvsp[(1) - (3)].filename_list)->next = (yyvsp[(3) - (3)].filename_list); @@ -2036,16 +1971,14 @@ yyreduce: break; case 46: - -/* Line 1806 of yacc.c */ -#line 369 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 361 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.filename_list) = (yyvsp[(1) - (1)].filename_list); } break; case 49: - -/* Line 1806 of yacc.c */ -#line 377 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 369 "/home/mark/src/elfutils/src/ldscript.y" { /* First little optimization. If there is only one file in the group don't do anything. */ @@ -2059,23 +1992,20 @@ yyreduce: break; case 50: - -/* Line 1806 of yacc.c */ -#line 388 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 380 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.filename_list) = mark_as_needed ((yyvsp[(3) - (4)].filename_list)); } break; case 51: - -/* Line 1806 of yacc.c */ -#line 390 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 382 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.filename_list) = new_filename_listelem ((yyvsp[(1) - (1)].str)); } break; case 52: - -/* Line 1806 of yacc.c */ -#line 395 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 387 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(2) - (2)].version)->next = (yyvsp[(1) - (2)].version)->next; (yyval.version) = (yyvsp[(1) - (2)].version)->next = (yyvsp[(2) - (2)].version); @@ -2083,16 +2013,14 @@ yyreduce: break; case 53: - -/* Line 1806 of yacc.c */ -#line 400 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 392 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.version) = (yyvsp[(1) - (1)].version); } break; case 54: - -/* Line 1806 of yacc.c */ -#line 404 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 396 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(2) - (4)].version)->versionname = ""; (yyvsp[(2) - (4)].version)->parentname = NULL; @@ -2101,9 +2029,8 @@ yyreduce: break; case 55: - -/* Line 1806 of yacc.c */ -#line 410 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 402 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(3) - (5)].version)->versionname = (yyvsp[(1) - (5)].str); (yyvsp[(3) - (5)].version)->parentname = NULL; @@ -2112,9 +2039,8 @@ yyreduce: break; case 56: - -/* Line 1806 of yacc.c */ -#line 416 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 408 "/home/mark/src/elfutils/src/ldscript.y" { (yyvsp[(3) - (6)].version)->versionname = (yyvsp[(1) - (6)].str); (yyvsp[(3) - (6)].version)->parentname = (yyvsp[(5) - (6)].str); @@ -2123,37 +2049,32 @@ yyreduce: break; case 57: - -/* Line 1806 of yacc.c */ -#line 425 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 417 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.version) = merge_versions ((yyvsp[(1) - (2)].version), (yyvsp[(2) - (2)].version)); } break; case 58: - -/* Line 1806 of yacc.c */ -#line 427 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 419 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.version) = (yyvsp[(1) - (1)].version); } break; case 59: - -/* Line 1806 of yacc.c */ -#line 431 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 423 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.version) = new_version (NULL, (yyvsp[(2) - (2)].id_list)); } break; case 60: - -/* Line 1806 of yacc.c */ -#line 433 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 425 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.version) = new_version ((yyvsp[(2) - (2)].id_list), NULL); } break; case 61: - -/* Line 1806 of yacc.c */ -#line 438 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 430 "/home/mark/src/elfutils/src/ldscript.y" { struct id_list *newp = new_id_listelem ((yyvsp[(2) - (3)].str)); newp->next = (yyvsp[(1) - (3)].id_list)->next; @@ -2162,44 +2083,38 @@ yyreduce: break; case 62: - -/* Line 1806 of yacc.c */ -#line 444 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 436 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.id_list) = new_id_listelem ((yyvsp[(1) - (2)].str)); } break; case 63: - -/* Line 1806 of yacc.c */ -#line 448 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 440 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = (yyvsp[(1) - (1)].str); } break; case 64: - -/* Line 1806 of yacc.c */ -#line 450 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 442 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = (yyvsp[(1) - (1)].str); } break; case 65: - -/* Line 1806 of yacc.c */ -#line 454 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 446 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = (yyvsp[(1) - (1)].str); } break; case 66: - -/* Line 1806 of yacc.c */ -#line 456 "ldscript.y" +/* Line 1792 of yacc.c */ +#line 448 "/home/mark/src/elfutils/src/ldscript.y" { (yyval.str) = NULL; } break; - -/* Line 1806 of yacc.c */ -#line 2203 "ldscript.c" +/* Line 1792 of yacc.c */ +#line 2118 "ldscript.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2362,7 +2277,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -2386,7 +2303,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -2428,9 +2345,8 @@ yyreturn: } - -/* Line 2067 of yacc.c */ -#line 459 "ldscript.y" +/* Line 2055 of yacc.c */ +#line 451 "/home/mark/src/elfutils/src/ldscript.y" static void @@ -2784,4 +2700,3 @@ add_versions (struct version *versions) } while (versions != NULL); } - diff --git a/src/src/ldscript.h b/src/src/ldscript.h index e33b803d..6442d673 100644 --- a/src/src/ldscript.h +++ b/src/src/ldscript.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +30,15 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_LD_LDSCRIPT_H_INCLUDED +# define YY_LD_LDSCRIPT_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int lddebug; +#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -97,13 +106,11 @@ - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { - -/* Line 2068 of yacc.c */ -#line 71 "ldscript.y" +/* Line 2058 of yacc.c */ +#line 63 "/home/mark/src/elfutils/src/ldscript.y" uintmax_t num; enum expression_tag op; @@ -119,9 +126,8 @@ typedef union YYSTYPE struct id_list *id_list; - -/* Line 2068 of yacc.c */ -#line 125 "ldscript.h" +/* Line 2058 of yacc.c */ +#line 131 "ldscript.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -130,4 +136,18 @@ typedef union YYSTYPE extern YYSTYPE ldlval; +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int ldparse (void *YYPARSE_PARAM); +#else +int ldparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int ldparse (void); +#else +int ldparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_LD_LDSCRIPT_H_INCLUDED */ diff --git a/src/src/ldscript.y b/src/src/ldscript.y index c2f1971a..ec58e21a 100644 --- a/src/src/ldscript.y +++ b/src/src/ldscript.y @@ -1,29 +1,21 @@ %{ /* Parser for linker scripts. Copyright (C) 2001-2011 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/nm.c b/src/src/nm.c index f33302a4..4f2e0e78 100644 --- a/src/src/nm.c +++ b/src/src/nm.c @@ -1,28 +1,20 @@ /* Print symbol information from ELF file in human-readable form. - Copyright (C) 2000-2008, 2009, 2011, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2000-2008, 2009, 2011, 2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2000. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -771,14 +763,16 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, { GElf_Shdr shdr_mem; - assert (elf_ndxscn (scn) == cnt++); + assert (elf_ndxscn (scn) == cnt); + cnt++; char *name = elf_strptr (ebl->elf, shstrndx, gelf_getshdr (scn, &shdr_mem)->sh_name); if (unlikely (name == NULL)) { - name = alloca (sizeof "[invalid sh_name 0x12345678]"); - snprintf (name, sizeof name, "[invalid sh_name %#" PRIx32 "]", + const size_t bufsz = sizeof "[invalid sh_name 0x12345678]"; + name = alloca (bufsz); + snprintf (name, bufsz, "[invalid sh_name %#" PRIx32 "]", gelf_getshdr (scn, &shdr_mem)->sh_name); } scnnames[elf_ndxscn (scn)] = name; @@ -800,15 +794,6 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, /* TRANS: the "sysv|" parts makes the string unique. */ longest_where, sgettext ("sysv|Line")); - /* Which format string to use (different radix for numbers). */ - const char *number_fmtstr; - if (radix == radix_hex) - number_fmtstr = "%0*" PRIx64; - else if (radix == radix_decimal) - number_fmtstr = "%0*" PRId64; - else - number_fmtstr = "%0*" PRIo64; - #ifdef USE_DEMANGLE size_t demangle_buffer_len = 0; char *demangle_buffer = NULL; @@ -826,8 +811,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, symstrbuf, sizeof symstrbuf); #ifdef USE_DEMANGLE - /* Demangle if necessary. */ - if (demangle) + /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ + if (demangle && symstr[0] == '_' && symstr[1] == 'Z') { int status = -1; char *dmsymstr = __cxa_demangle (symstr, demangle_buffer, @@ -856,9 +841,15 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname, addressbuf[0] = sizebuf[0] = '\0'; else { - snprintf (addressbuf, sizeof (addressbuf), number_fmtstr, + snprintf (addressbuf, sizeof (addressbuf), + (radix == radix_hex ? "%0*" PRIx64 + : (radix == radix_decimal ? "%0*" PRId64 + : "%0*" PRIo64)), digits, syms[cnt].sym.st_value); - snprintf (sizebuf, sizeof (sizebuf), number_fmtstr, + snprintf (sizebuf, sizeof (sizebuf), + (radix == radix_hex ? "%0*" PRIx64 + : (radix == radix_decimal ? "%0*" PRId64 + : "%0*" PRIo64)), digits, syms[cnt].sym.st_size); } @@ -935,19 +926,6 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, if (prefix != NULL && ! print_file_name) printf ("\n%s:\n", fname); - static const char *const fmtstrs[] = - { - [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %9$s%3$c%4$s %5$s", - [radix_decimal] = "%8$s%*" PRId64 "%10$s %9$s%3$c%4$s %5$s", - [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %9$s%3$c%4$s %5$s" - }; - static const char *const sfmtstrs[] = - { - [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %7$0*6$" PRIx64 " %9$s%3$c%4$s %5$s", - [radix_decimal] = "%8$s%2$*1$" PRId64 "%10$s %7$*6$" PRId64 " %9$s%3$c%4$s %5$s", - [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %7$0*6$" PRIo64 " %9$s%3$c%4$s %5$s" - }; - #ifdef USE_DEMANGLE size_t demangle_buffer_len = 0; char *demangle_buffer = NULL; @@ -971,8 +949,8 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, continue; #ifdef USE_DEMANGLE - /* Demangle if necessary. */ - if (demangle) + /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ + if (demangle && symstr[0] == '_' && symstr[1] == 'Z') { int status = -1; char *dmsymstr = __cxa_demangle (symstr, demangle_buffer, @@ -1022,16 +1000,41 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, else color = color_symbol; } - - printf (print_size && syms[cnt].sym.st_size != 0 - ? sfmtstrs[radix] : fmtstrs[radix], - digits, syms[cnt].sym.st_value, - class_type_char (elf, ehdr, &syms[cnt].sym), marker, - symstr, - digits, (uint64_t) syms[cnt].sym.st_size, - color_mode ? color_address : "", - color, - color_mode ? color_off : ""); + if (print_size && syms[cnt].sym.st_size != 0) + { +#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %10$0*9$" PRIx64 " %7$s%3$c%4$s %5$s" +#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %10$*9$" PRId64 " %7$s%3$c%4$s %5$s" +#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %10$0*9$" PRIo64 " %7$s%3$c%4$s %5$s" + printf ((radix == radix_hex ? HEXFMT + : (radix == radix_decimal ? DECFMT : OCTFMT)), + digits, syms[cnt].sym.st_value, + class_type_char (elf, ehdr, &syms[cnt].sym), marker, + symstr, + color_mode ? color_address : "", + color, + color_mode ? color_off : "", + digits, (uint64_t) syms[cnt].sym.st_size); +#undef HEXFMT +#undef DECFMT +#undef OCTFMT + } + else + { +#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %7$s%3$c%4$s %5$s" +#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %7$s%3$c%4$s %5$s" +#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %7$s%3$c%4$s %5$s" + printf ((radix == radix_hex ? HEXFMT + : (radix == radix_decimal ? DECFMT : OCTFMT)), + digits, syms[cnt].sym.st_value, + class_type_char (elf, ehdr, &syms[cnt].sym), marker, + symstr, + color_mode ? color_address : "", + color, + color_mode ? color_off : ""); +#undef HEXFMT +#undef DECFMT +#undef OCTFMT + } } if (color_mode) @@ -1053,14 +1056,6 @@ show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, if (prefix != NULL && ! print_file_name) printf ("%s:\n", fullname); - const char *fmtstr; - if (radix == radix_hex) - fmtstr = "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n"; - else if (radix == radix_decimal) - fmtstr = "%s %c%s %*" PRId64 " %*" PRId64 "\n"; - else - fmtstr = "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n"; - int digits = length_map[gelf_getclass (elf) - 1][radix]; #ifdef USE_DEMANGLE @@ -1082,8 +1077,8 @@ show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, continue; #ifdef USE_DEMANGLE - /* Demangle if necessary. */ - if (demangle) + /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ + if (demangle && symstr[0] == '_' && symstr[1] == 'Z') { int status = -1; char *dmsymstr = __cxa_demangle (symstr, demangle_buffer, @@ -1102,7 +1097,11 @@ show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx, putchar_unlocked (' '); } - printf (fmtstr, + printf ((radix == radix_hex + ? "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n" + : (radix == radix_decimal + ? "%s %c%s %*" PRId64 " %*" PRId64 "\n" + : "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n")), symstr, class_type_char (elf, ehdr, &syms[cnt].sym), mark_special @@ -1250,8 +1249,8 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn, continue; #ifdef USE_DEMANGLE - /* Demangle if necessary. */ - if (demangle) + /* Demangle if necessary. Require GNU v3 ABI by the "_Z" prefix. */ + if (demangle && symstr[0] == '_' && symstr[1] == 'Z') { int status = -1; char *dmsymstr = __cxa_demangle (symstr, demangle_buffer, diff --git a/src/src/objdump.c b/src/src/objdump.c index e2fcfbf1..87290ccb 100644 --- a/src/src/objdump.c +++ b/src/src/objdump.c @@ -1,28 +1,20 @@ /* Print information from ELF file in human-readable form. - Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -397,7 +389,7 @@ show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata, ? xndx : sym->st_shndx), &destshdr_mem); - if (shdr == NULL) + if (shdr == NULL || destshdr == NULL) printf ("<%s %ld>", gettext ("INVALID SECTION"), (long int) (sym->st_shndx == SHN_XINDEX @@ -426,7 +418,8 @@ show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx) { - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; for (int cnt = 0; cnt < nentries; ++cnt) { @@ -446,7 +439,8 @@ show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx) { - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; for (int cnt = 0; cnt < nentries; ++cnt) { @@ -468,13 +462,13 @@ section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx) return true; struct section_list *runp = section_list; + const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); do { if (runp->is_name) { - if (strcmp (runp->name, - elf_strptr (elf, shstrndx, shdr->sh_name)) == 0) + if (name && strcmp (runp->name, name) == 0) return true; } else @@ -514,6 +508,8 @@ show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx) GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info), &destshdr_mem); + if (unlikely (destshdr == NULL)) + continue; printf (gettext ("\nRELOCATION RECORDS FOR [%s]:\n" "%-*s TYPE VALUE\n"), @@ -530,6 +526,8 @@ show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx) GElf_Shdr symshdr_mem; GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem); Elf_Data *symdata = elf_getdata (symscn, NULL); + if (unlikely (symshdr == NULL || symdata == NULL)) + continue; /* Search for the optional extended section index table. */ Elf_Data *xndxdata = NULL; diff --git a/src/src/ranlib.c b/src/src/ranlib.c index d30fc320..8435fc1b 100644 --- a/src/src/ranlib.c +++ b/src/src/ranlib.c @@ -1,28 +1,20 @@ /* Generate an index to speed access to archives. Copyright (C) 2005-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/readelf.c b/src/src/readelf.c index 88766889..df0a874d 100644 --- a/src/src/readelf.c +++ b/src/src/readelf.c @@ -1,28 +1,20 @@ /* Print information from ELF file in human-readable form. - Copyright (C) 1999-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 1999-2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 1999. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -50,6 +42,7 @@ #include <unistd.h> #include <sys/param.h> #include <sys/stat.h> +#include <signal.h> #include <system.h> #include "../libelf/libelfP.h" @@ -59,6 +52,8 @@ #include "../libdwfl/libdwflP.h" #include "../libdw/memory-access.h" +#include "../libdw/known-dwarf.h" + /* Name and version of program. */ static void print_version (FILE *stream, struct argp_state *state); @@ -67,9 +62,16 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; /* Bug report address. */ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; +/* argp key value for --elf-section, non-ascii. */ +#define ELF_INPUT_SECTION 256 + /* Definitions of arguments for argp functions. */ static const struct argp_option options[] = { + { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 }, + { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL, + N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF " + "input data"), 0 }, { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 }, { "all", 'a', NULL, 0, N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 }, @@ -93,8 +95,8 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 }, { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " - "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, " - "macinfo, or exception"), 0 }, + "aranges, decodedaranges, frame, gdb_index, info, loc, line, " + "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, @@ -106,6 +108,8 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Output control:"), 0 }, { "numeric-addresses", 'N', NULL, 0, N_("Do not find symbol names for addresses in DWARF data"), 0 }, + { "unresolved-address-offsets", 'U', NULL, 0, + N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 }, { "wide", 'W', NULL, 0, N_("Ignored for compatibility (lines always wide)"), 0 }, { NULL, 0, NULL, 0, NULL, 0 } @@ -127,6 +131,8 @@ static struct argp argp = options, parse_opt, args_doc, doc, NULL, NULL, NULL }; +/* If non-null, the section from which we should read to (compressed) ELF. */ +static const char *elf_input_section = NULL; /* Flags set by the option controlling the output. */ @@ -175,6 +181,15 @@ static bool any_control_option; /* True if we should print addresses from DWARF in symbolic form. */ static bool print_address_names = true; +/* True if we should print raw values instead of relativized addresses. */ +static bool print_unresolved_addresses = false; + +/* True if we should print the .debug_aranges section using libdw. */ +static bool decodedaranges = false; + +/* True if we should print the .debug_aranges section using libdw. */ +static bool decodedline = false; + /* Select printing of debugging sections. */ static enum section_e { @@ -191,10 +206,12 @@ static enum section_e section_ranges = 512, /* .debug_ranges */ section_exception = 1024, /* .eh_frame & al. */ section_gdb_index = 2048, /* .gdb_index */ + section_macro = 4096, /* .debug_macro */ section_all = (section_abbrev | section_aranges | section_frame | section_info | section_line | section_loc | section_pubnames | section_str | section_macinfo - | section_ranges | section_exception | section_gdb_index) + | section_ranges | section_exception | section_gdb_index + | section_macro) } print_debug_sections, implicit_debug_sections; /* Select hex dumping of sections. */ @@ -381,6 +398,11 @@ parse_opt (int key, char *arg, print_debug_sections |= section_abbrev; else if (strcmp (arg, "aranges") == 0) print_debug_sections |= section_aranges; + else if (strcmp (arg, "decodedaranges") == 0) + { + print_debug_sections |= section_aranges; + decodedaranges = true; + } else if (strcmp (arg, "ranges") == 0) { print_debug_sections |= section_ranges; @@ -397,12 +419,19 @@ parse_opt (int key, char *arg, } else if (strcmp (arg, "line") == 0) print_debug_sections |= section_line; + else if (strcmp (arg, "decodedline") == 0) + { + print_debug_sections |= section_line; + decodedline = true; + } else if (strcmp (arg, "pubnames") == 0) print_debug_sections |= section_pubnames; else if (strcmp (arg, "str") == 0) print_debug_sections |= section_str; else if (strcmp (arg, "macinfo") == 0) print_debug_sections |= section_macinfo; + else if (strcmp (arg, "macro") == 0) + print_debug_sections |= section_macro; else if (strcmp (arg, "exception") == 0) print_debug_sections |= section_exception; else if (strcmp (arg, "gdb_index") == 0) @@ -432,6 +461,9 @@ parse_opt (int key, char *arg, case 'N': print_address_names = false; break; + case 'U': + print_unresolved_addresses = true; + break; case ARGP_KEY_NO_ARGS: fputs (gettext ("Missing file name.\n"), stderr); goto do_argp_help; @@ -447,6 +479,12 @@ parse_opt (int key, char *arg, break; case 'W': /* Ignored. */ break; + case ELF_INPUT_SECTION: + if (arg == NULL) + elf_input_section = ".gnu_debugdata"; + else + elf_input_section = arg; + break; default: return ARGP_ERR_UNKNOWN; } @@ -468,6 +506,121 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ } +/* Create a file descriptor to read the data from the + elf_input_section given a file descriptor to an ELF file. */ +static int +open_input_section (int fd) +{ + size_t shnums; + size_t cnt; + size_t shstrndx; + Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL); + if (elf == NULL) + { + error (0, 0, gettext ("cannot generate Elf descriptor: %s"), + elf_errmsg (-1)); + return -1; + } + + if (elf_getshdrnum (elf, &shnums) < 0) + { + error (0, 0, gettext ("cannot determine number of sections: %s"), + elf_errmsg (-1)); + open_error: + elf_end (elf); + return -1; + } + + if (elf_getshdrstrndx (elf, &shstrndx) < 0) + { + error (0, 0, gettext ("cannot get section header string table index")); + goto open_error; + } + + for (cnt = 0; cnt < shnums; ++cnt) + { + Elf_Scn *scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + error (0, 0, gettext ("cannot get section: %s"), + elf_errmsg (-1)); + goto open_error; + } + + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (unlikely (shdr == NULL)) + { + error (0, 0, gettext ("cannot get section header: %s"), + elf_errmsg (-1)); + goto open_error; + } + + const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name); + if (sname == NULL) + { + error (0, 0, gettext ("cannot get section name")); + goto open_error; + } + + if (strcmp (sname, elf_input_section) == 0) + { + Elf_Data *data = elf_rawdata (scn, NULL); + if (data == NULL) + { + error (0, 0, gettext ("cannot get %s content: %s"), + sname, elf_errmsg (-1)); + goto open_error; + } + + /* Create (and immediately unlink) a temporary file to store + section data in to create a file descriptor for it. */ + const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir; + static const char suffix[] = "/readelfXXXXXX"; + int tmplen = strlen (tmpdir) + sizeof (suffix); + char *tempname = alloca (tmplen); + sprintf (tempname, "%s%s", tmpdir, suffix); + + int sfd = mkstemp (tempname); + if (sfd == -1) + { + error (0, 0, gettext ("cannot create temp file '%s'"), + tempname); + goto open_error; + } + unlink (tempname); + + ssize_t size = data->d_size; + if (write_retry (sfd, data->d_buf, size) != size) + { + error (0, 0, gettext ("cannot write section data")); + goto open_error; + } + + if (elf_end (elf) != 0) + { + error (0, 0, gettext ("error while closing Elf descriptor: %s"), + elf_errmsg (-1)); + return -1; + } + + if (lseek (sfd, 0, SEEK_SET) == -1) + { + error (0, 0, gettext ("error while rewinding file descriptor")); + return -1; + } + + return sfd; + } + } + + /* Named section not found. */ + if (elf_end (elf) != 0) + error (0, 0, gettext ("error while closing Elf descriptor: %s"), + elf_errmsg (-1)); + return -1; +} + /* Check if the file is an archive, and if so dump its index. */ static void check_archive_index (int fd, const char *fname, bool only_one) @@ -540,18 +693,32 @@ process_dwflmod (Dwfl_Module *dwflmod, return DWARF_CB_OK; } -/* Stub libdwfl callback, only the ELF handle already open is ever used. */ +/* Stub libdwfl callback, only the ELF handle already open is ever used. + Only used for finding the alternate debug file if the Dwarf comes from + the main file. We are not interested in separate debuginfo. */ static int -find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)), - void **userdata __attribute__ ((unused)), - const char *modname __attribute__ ((unused)), - Dwarf_Addr base __attribute__ ((unused)), - const char *file_name __attribute__ ((unused)), - const char *debuglink_file __attribute__ ((unused)), - GElf_Word debuglink_crc __attribute__ ((unused)), - char **debuginfo_file_name __attribute__ ((unused))) +find_no_debuginfo (Dwfl_Module *mod, + void **userdata, + const char *modname, + Dwarf_Addr base, + const char *file_name, + const char *debuglink_file, + GElf_Word debuglink_crc, + char **debuginfo_file_name) { - return -1; + Dwarf_Addr dwbias; + dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL); + + /* We are only interested if the Dwarf has been setup on the main + elf file but is only missing the alternate debug link. If dwbias + hasn't even been setup, this is searching for separate debuginfo + for the main elf. We don't care in that case. */ + if (dwbias == (Dwarf_Addr) -1) + return -1; + + return dwfl_standard_find_debuginfo (mod, userdata, modname, base, + file_name, debuglink_file, + debuglink_crc, debuginfo_file_name); } /* Process one input file. */ @@ -564,6 +731,21 @@ process_file (int fd, const char *fname, bool only_one) if (!any_control_option) return; + if (elf_input_section != NULL) + { + /* Replace fname and fd with section content. */ + char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2); + sprintf (fnname, "%s:%s", fname, elf_input_section); + fd = open_input_section (fd); + if (fd == -1) + { + error (0, 0, gettext ("No such section '%s' in '%s'"), + elf_input_section, fname); + return; + } + fname = fnname; + } + /* Duplicate an fd for dwfl_report_offline to swallow. */ int dwfl_fd = dup (fd); if (unlikely (dwfl_fd < 0)) @@ -608,6 +790,11 @@ process_file (int fd, const char *fname, bool only_one) dwfl_getmodules (dwfl, &process_dwflmod, &a, 0); } dwfl_end (dwfl); + + /* Need to close the replaced fd if we created it. Caller takes + care of original. */ + if (elf_input_section != NULL) + close (fd); } @@ -970,7 +1157,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\ static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) { - if (ehdr->e_phnum == 0) + if (phnum == 0) /* No program header, this is OK in relocatable objects. */ return; @@ -1014,11 +1201,28 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) if (phdr->p_type == PT_INTERP) { - /* We can show the user the name of the interpreter. */ + /* If we are sure the file offset is valid then we can show + the user the name of the interpreter. We check whether + there is a section at the file offset. Normally there + would be a section called ".interp". But in separate + .debug files it is a NOBITS section (and so doesn't match + with gelf_offscn). Which probably means the offset is + not valid another reason could be because the ELF file + just doesn't contain any section headers, in that case + just play it safe and don't display anything. */ + + Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset); + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + size_t maxsize; char *filedata = elf_rawfile (ebl->elf, &maxsize); - if (filedata != NULL && phdr->p_offset < maxsize) + if (shdr != NULL && shdr->sh_type == SHT_PROGBITS + && filedata != NULL && phdr->p_offset < maxsize + && phdr->p_filesz <= maxsize - phdr->p_offset + && memchr (filedata + phdr->p_offset, '\0', + phdr->p_filesz) != NULL) printf (gettext ("\t[Requesting program interpreter: %s]\n"), filedata + phdr->p_offset); } @@ -1191,6 +1395,8 @@ handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Elf32_Word *grpref = (Elf32_Word *) data->d_buf; GElf_Sym sym_mem; + GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem); + printf ((grpref[0] & GRP_COMDAT) ? ngettext ("\ \nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n", @@ -1203,8 +1409,8 @@ handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) data->d_size / sizeof (Elf32_Word) - 1), elf_ndxscn (scn), elf_strptr (ebl->elf, shstrndx, shdr->sh_name), - elf_strptr (ebl->elf, symshdr->sh_link, - gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name) + (sym == NULL ? NULL + : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)) ?: gettext ("<INVALID SYMBOL>"), data->d_size / sizeof (Elf32_Word) - 1); @@ -1355,10 +1561,12 @@ static void handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); - GElf_Shdr glink; + GElf_Shdr glink_mem; + GElf_Shdr *glink; Elf_Data *data; size_t cnt; size_t shstrndx; + size_t sh_entsize; /* Get the data of the section. */ data = elf_getdata (scn, NULL); @@ -1370,21 +1578,26 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); + sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT); + + glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + printf (ngettext ("\ \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", - shdr->sh_size / shdr->sh_entsize), - (unsigned long int) (shdr->sh_size / shdr->sh_entsize), + shdr->sh_size / sh_entsize), + (unsigned long int) (shdr->sh_size / sh_entsize), class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); fputs_unlocked (gettext (" Type Value\n"), stdout); - for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { GElf_Dyn dynmem; GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); @@ -1533,7 +1746,8 @@ static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; /* Get the data of the section. */ Elf_Data *data = elf_getdata (scn, NULL); @@ -1680,12 +1894,15 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); else { - destshdr = gelf_getshdr (elf_getscn (ebl->elf, - sym->st_shndx == SHN_XINDEX - ? xndx : sym->st_shndx), - &destshdr_mem); - - if (unlikely (destshdr == NULL)) + /* This is a relocation against a STT_SECTION symbol. */ + GElf_Shdr secshdr_mem; + GElf_Shdr *secshdr; + secshdr = gelf_getshdr (elf_getscn (ebl->elf, + sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx), + &secshdr_mem); + + if (unlikely (secshdr == NULL)) printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset, ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) @@ -1707,7 +1924,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) buf, sizeof (buf)) + 2 : gettext ("<INVALID RELOC>"), class == ELFCLASS32 ? 10 : 18, sym->st_value, - elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); } } } @@ -1719,7 +1936,8 @@ static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; /* Get the data of the section. */ Elf_Data *data = elf_getdata (scn, NULL); @@ -1756,7 +1974,8 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); - printf (ngettext ("\ + if (shdr->sh_info != 0) + printf (ngettext ("\ \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", "\ \nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", @@ -1767,6 +1986,19 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) elf_strptr (ebl->elf, shstrndx, destshdr->sh_name), shdr->sh_offset, nentries); + else + /* The .rela.dyn section does not refer to a specific section but + instead of section index zero. Do not try to print a section + name. */ + printf (ngettext ("\ +\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n", + "\ +\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n", + nentries), + (unsigned int) elf_ndxscn (scn), + elf_strptr (ebl->elf, shstrndx, shdr->sh_name), + shdr->sh_offset, + nentries); fputs_unlocked (class == ELFCLASS32 ? gettext ("\ Offset Type Value Addend Name\n") @@ -1856,12 +2088,15 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); else { - destshdr = gelf_getshdr (elf_getscn (ebl->elf, - sym->st_shndx == SHN_XINDEX - ? xndx : sym->st_shndx), - &destshdr_mem); - - if (unlikely (shdr == NULL)) + /* This is a relocation against a STT_SECTION symbol. */ + GElf_Shdr secshdr_mem; + GElf_Shdr *secshdr; + secshdr = gelf_getshdr (elf_getscn (ebl->elf, + sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx), + &secshdr_mem); + + if (unlikely (secshdr == NULL)) printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset, ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) @@ -1885,7 +2120,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) : gettext ("<INVALID RELOC>"), class == ELFCLASS32 ? 10 : 18, sym->st_value, rel->r_addend, - elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); } } } @@ -1966,6 +2201,13 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), + &glink_mem); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + /* Now we can compute the number of entries in the section. */ unsigned int nsyms = data->d_size / (class == ELFCLASS32 ? sizeof (Elf32_Sym) @@ -1976,15 +2218,12 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) nsyms), (unsigned int) elf_ndxscn (scn), elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms); - GElf_Shdr glink; printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n", " %lu local symbols String table: [%2u] '%s'\n", shdr->sh_info), (unsigned long int) shdr->sh_info, (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); fputs_unlocked (class == ELFCLASS32 ? gettext ("\ @@ -2220,7 +2459,13 @@ handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); - GElf_Shdr glink; + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), + &glink_mem); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + printf (ngettext ("\ \nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ @@ -2231,9 +2476,7 @@ handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); unsigned int offset = 0; for (int cnt = shdr->sh_info; --cnt >= 0; ) @@ -2263,10 +2506,16 @@ handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) get_ver_flags (aux->vna_flags), (unsigned short int) aux->vna_other); + if (aux->vna_next == 0) + break; + auxoffset += aux->vna_next; } /* Find the next offset. */ + if (need->vn_next == 0) + break; + offset += need->vn_next; } } @@ -2286,8 +2535,14 @@ handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), + &glink_mem); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + int class = gelf_getclass (ebl->elf); - GElf_Shdr glink; printf (ngettext ("\ \nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ @@ -2299,9 +2554,7 @@ handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); unsigned int offset = 0; for (int cnt = shdr->sh_info; --cnt >= 0; ) @@ -2337,10 +2590,15 @@ handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) auxoffset, cnt2, elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name)); + if (aux->vda_next == 0) + break; + auxoffset += aux->vda_next; } /* Find the next offset. */ + if (def->vd_next == 0) + break; offset += def->vd_next; } } @@ -2419,6 +2677,8 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff)); + if (def->vd_next == 0) + break; offset += def->vd_next; } } @@ -2463,9 +2723,13 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) nvername = MAX (nvername, (size_t) (aux->vna_other & 0x7fff)); + if (aux->vna_next == 0) + break; auxoffset += aux->vna_next; } + if (need->vn_next == 0) + break; offset += need->vn_next; } } @@ -2475,7 +2739,9 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Allocate the array. */ vername = (const char **) alloca (nvername * sizeof (const char *)); + memset(vername, 0, nvername * sizeof (const char *)); filename = (const char **) alloca (nvername * sizeof (const char *)); + memset(filename, 0, nvername * sizeof (const char *)); /* Run through the data structures again and collect the strings. */ if (defscn != NULL) @@ -2501,17 +2767,22 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the data at the next offset. */ GElf_Verdef defmem; GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem); + if (unlikely (def == NULL)) + break; + GElf_Verdaux auxmem; GElf_Verdaux *aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem); - if (unlikely (def == NULL || aux == NULL)) + if (unlikely (aux == NULL)) break; vername[def->vd_ndx & 0x7fff] = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name); filename[def->vd_ndx & 0x7fff] = NULL; + if (def->vd_next == 0) + break; offset += def->vd_next; } } @@ -2549,9 +2820,13 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) filename[aux->vna_other & 0x7fff] = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file); + if (aux->vna_next == 0) + break; auxoffset += aux->vna_next; } + if (need->vn_next == 0) + break; offset += need->vn_next; } } @@ -2563,25 +2838,30 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) filename = NULL; } + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), + &glink_mem); + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + /* Print the header. */ - GElf_Shdr glink; printf (ngettext ("\ \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", "\ \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", - shdr->sh_size / shdr->sh_entsize), + shdr->sh_size / sh_entsize), (unsigned int) elf_ndxscn (scn), elf_strptr (ebl->elf, shstrndx, shdr->sh_name), - (int) (shdr->sh_size / shdr->sh_entsize), + (int) (shdr->sh_size / sh_entsize), class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); /* Now we can finally look at the actual contents of this section. */ - for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { if (cnt % 2 == 0) printf ("\n %4d:", cnt); @@ -2607,10 +2887,11 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) default: n = printf ("%4d%c%s", *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ', - (unsigned int) (*sym & 0x7fff) < nvername + (vername != NULL + && (unsigned int) (*sym & 0x7fff) < nvername) ? vername[*sym & 0x7fff] : "???"); if ((unsigned int) (*sym & 0x7fff) < nvername - && filename[*sym & 0x7fff] != NULL) + && filename != NULL && filename[*sym & 0x7fff] != NULL) n += printf ("(%s)", filename[*sym & 0x7fff]); printf ("%*s", MAX (0, 33 - (int) n), " "); break; @@ -2630,7 +2911,17 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx, for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) ++counts[lengths[cnt]]; - GElf_Shdr glink; + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, + shdr->sh_link), + &glink_mem); + if (glink == NULL) + { + error (0, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + return; + } + printf (ngettext ("\ \nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ @@ -2643,9 +2934,7 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx, shdr->sh_addr, shdr->sh_offset, (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, - gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), - &glink)->sh_name)); + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); if (extrastr != NULL) fputs (extrastr, stdout); @@ -2700,8 +2989,21 @@ handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) return; } + if (unlikely (data->d_size < 2 * sizeof (Elf32_Word))) + { + invalid_data: + error (0, 0, gettext ("invalid data in sysv.hash section %d"), + (int) elf_ndxscn (scn)); + return; + } + Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1]; + + uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word); + if (used_buf > data->d_size) + goto invalid_data; + Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2]; Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket]; @@ -2742,8 +3044,23 @@ handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) return; } + if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword))) + { + invalid_data: + error (0, 0, gettext ("invalid data in sysv.hash64 section %d"), + (int) elf_ndxscn (scn)); + return; + } + Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0]; Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1]; + + uint64_t maxwords = data->d_size / sizeof (Elf64_Xword); + if (maxwords < 2 + || maxwords - 2 < nbucket + || maxwords - 2 - nbucket < nchain) + goto invalid_data; + Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2]; Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket]; @@ -2783,18 +3100,37 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) return; } + if (unlikely (data->d_size < 4 * sizeof (Elf32_Word))) + { + invalid_data: + error (0, 0, gettext ("invalid data in gnu.hash section %d"), + (int) elf_ndxscn (scn)); + return; + } + Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1]; /* Next comes the size of the bitmap. It's measured in words for the architecture. It's 32 bits for 32 bit archs, and 64 bits for - 64 bit archs. */ + 64 bit archs. There is always a bloom filter present, so zero is + an invalid value. */ Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2]; if (gelf_getclass (ebl->elf) == ELFCLASS64) bitmask_words *= 2; + if (bitmask_words == 0) + goto invalid_data; + Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3]; + /* Is there still room for the sym chain? + Use uint64_t calculation to prevent 32bit overlow. */ + uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word); + uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word); + if (used_buf > data->d_size) + goto invalid_data; + uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t)); Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4]; @@ -2814,6 +3150,8 @@ handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) ++nsyms; if (maxlength < ++lengths[cnt]) ++maxlength; + if (inner > max_nsyms) + goto invalid_data; } while ((chain[inner++] & 1) == 0); } @@ -2905,7 +3243,8 @@ print_liblist (Ebl *ebl) if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST) { - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; printf (ngettext ("\ \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n", "\ @@ -2978,11 +3317,12 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) shdr->sh_size, shdr->sh_offset); Elf_Data *data = elf_rawdata (scn, NULL); - if (data == NULL) + if (unlikely (data == NULL || data->d_size == 0)) return; const unsigned char *p = data->d_buf; + /* There is only one 'version', A. */ if (unlikely (*p++ != 'A')) return; @@ -2993,8 +3333,10 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) return (const unsigned char *) data->d_buf + data->d_size - p; } + /* Loop over the sections. */ while (left () >= 4) { + /* Section length. */ uint32_t len; memcpy (&len, p, sizeof len); @@ -3004,25 +3346,29 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) if (unlikely (len > left ())) break; + /* Section vendor name. */ const unsigned char *name = p + sizeof len; p += len; unsigned const char *q = memchr (name, '\0', len); if (unlikely (q == NULL)) - continue; + break; ++q; printf (gettext (" %-13s %4" PRIu32 "\n"), name, len); + bool gnu_vendor = (q - name == sizeof "gnu" + && !memcmp (name, "gnu", sizeof "gnu")); + + /* Loop over subsections. */ if (shdr->sh_type != SHT_GNU_ATTRIBUTES - || (q - name == sizeof "gnu" - && !memcmp (name, "gnu", sizeof "gnu"))) + || gnu_vendor) while (q < p) { const unsigned char *const sub = q; unsigned int subsection_tag; - get_uleb128 (subsection_tag, q); + get_uleb128 (subsection_tag, q, p); if (unlikely (q >= p)) break; @@ -3035,7 +3381,10 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) if (MY_ELFDATA != ehdr->e_ident[EI_DATA]) CONVERT (subsection_len); - if (unlikely (p - sub < (ptrdiff_t) subsection_len)) + /* Don't overflow, ptrdiff_t might be 32bits, but signed. */ + if (unlikely (subsection_len == 0 + || subsection_len >= (uint32_t) PTRDIFF_MAX + || p - sub < (ptrdiff_t) subsection_len)) break; const unsigned char *r = q + sizeof subsection_len; @@ -3044,6 +3393,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) switch (subsection_tag) { default: + /* Unknown subsection, print and skip. */ printf (gettext (" %-4u %12" PRIu32 "\n"), subsection_tag, subsection_len); break; @@ -3055,20 +3405,34 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) while (r < q) { unsigned int tag; - get_uleb128 (tag, r); + get_uleb128 (tag, r, q); if (unlikely (r >= q)) break; + /* GNU style tags have either a uleb128 value, + when lowest bit is not set, or a string + when the lowest bit is set. + "compatibility" (32) is special. It has + both a string and a uleb128 value. For + non-gnu we assume 6 till 31 only take ints. + XXX see arm backend, do we need a separate + hook? */ uint64_t value = 0; const char *string = NULL; - if (tag == 32 || (tag & 1) == 0) + if (tag == 32 || (tag & 1) == 0 + || (! gnu_vendor && (tag > 5 && tag < 32))) { - get_uleb128 (value, r); + get_uleb128 (value, r, q); if (r > q) break; } - if (tag == 32 || (tag & 1) != 0) + if (tag == 32 + || ((tag & 1) != 0 + && (gnu_vendor + || (! gnu_vendor && tag > 32))) + || (! gnu_vendor && tag > 3 && tag < 6)) { + string = (const char *) r; r = memchr (r, '\0', q - r); if (r == NULL) break; @@ -3095,7 +3459,10 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) } else { - assert (tag != 32); + /* For "gnu" vendor 32 "compatibility" has + already been handled above. */ + assert (tag != 32 + || strcmp ((const char *) name, "gnu")); if (string == NULL) printf (gettext (" %u: %" PRId64 "\n"), tag, value); @@ -3113,43 +3480,52 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) static char * format_dwarf_addr (Dwfl_Module *dwflmod, - int address_size, Dwarf_Addr address) + int address_size, Dwarf_Addr address, Dwarf_Addr raw) { /* See if there is a name we can give for this address. */ GElf_Sym sym; - const char *name = print_address_names - ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL; - if (name != NULL) - sym.st_value = address - sym.st_value; + GElf_Off off = 0; + const char *name = (print_address_names && ! print_unresolved_addresses) + ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL) + : NULL; - /* Relativize the address. */ - int n = dwfl_module_relocations (dwflmod); - int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address); + const char *scn; + if (print_unresolved_addresses) + { + address = raw; + scn = NULL; + } + else + { + /* Relativize the address. */ + int n = dwfl_module_relocations (dwflmod); + int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address); - /* In an ET_REL file there is a section name to refer to. */ - const char *scn = (i < 0 ? NULL - : dwfl_module_relocation_info (dwflmod, i, NULL)); + /* In an ET_REL file there is a section name to refer to. */ + scn = (i < 0 ? NULL + : dwfl_module_relocation_info (dwflmod, i, NULL)); + } char *result; if ((name != NULL - ? (sym.st_value != 0 + ? (off != 0 ? (scn != NULL ? (address_size == 0 ? asprintf (&result, gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"), - scn, address, name, sym.st_value) + scn, address, name, off) : asprintf (&result, gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"), scn, 2 + address_size * 2, address, - name, sym.st_value)) + name, off)) : (address_size == 0 ? asprintf (&result, gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"), - address, name, sym.st_value) + address, name, off) : asprintf (&result, gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"), 2 + address_size * 2, address, - name, sym.st_value))) + name, off))) : (scn != NULL ? (address_size == 0 ? asprintf (&result, @@ -3188,521 +3564,58 @@ format_dwarf_addr (Dwfl_Module *dwflmod, static const char * dwarf_tag_string (unsigned int tag) { - static const char *const known_tags[] = - { - [DW_TAG_array_type] = "array_type", - [DW_TAG_class_type] = "class_type", - [DW_TAG_entry_point] = "entry_point", - [DW_TAG_enumeration_type] = "enumeration_type", - [DW_TAG_formal_parameter] = "formal_parameter", - [DW_TAG_imported_declaration] = "imported_declaration", - [DW_TAG_label] = "label", - [DW_TAG_lexical_block] = "lexical_block", - [DW_TAG_member] = "member", - [DW_TAG_pointer_type] = "pointer_type", - [DW_TAG_reference_type] = "reference_type", - [DW_TAG_compile_unit] = "compile_unit", - [DW_TAG_string_type] = "string_type", - [DW_TAG_structure_type] = "structure_type", - [DW_TAG_subroutine_type] = "subroutine_type", - [DW_TAG_typedef] = "typedef", - [DW_TAG_union_type] = "union_type", - [DW_TAG_unspecified_parameters] = "unspecified_parameters", - [DW_TAG_variant] = "variant", - [DW_TAG_common_block] = "common_block", - [DW_TAG_common_inclusion] = "common_inclusion", - [DW_TAG_inheritance] = "inheritance", - [DW_TAG_inlined_subroutine] = "inlined_subroutine", - [DW_TAG_module] = "module", - [DW_TAG_ptr_to_member_type] = "ptr_to_member_type", - [DW_TAG_set_type] = "set_type", - [DW_TAG_subrange_type] = "subrange_type", - [DW_TAG_with_stmt] = "with_stmt", - [DW_TAG_access_declaration] = "access_declaration", - [DW_TAG_base_type] = "base_type", - [DW_TAG_catch_block] = "catch_block", - [DW_TAG_const_type] = "const_type", - [DW_TAG_constant] = "constant", - [DW_TAG_enumerator] = "enumerator", - [DW_TAG_file_type] = "file_type", - [DW_TAG_friend] = "friend", - [DW_TAG_namelist] = "namelist", - [DW_TAG_namelist_item] = "namelist_item", - [DW_TAG_packed_type] = "packed_type", - [DW_TAG_subprogram] = "subprogram", - [DW_TAG_template_type_parameter] = "template_type_parameter", - [DW_TAG_template_value_parameter] = "template_value_parameter", - [DW_TAG_thrown_type] = "thrown_type", - [DW_TAG_try_block] = "try_block", - [DW_TAG_variant_part] = "variant_part", - [DW_TAG_variable] = "variable", - [DW_TAG_volatile_type] = "volatile_type", - [DW_TAG_dwarf_procedure] = "dwarf_procedure", - [DW_TAG_restrict_type] = "restrict_type", - [DW_TAG_interface_type] = "interface_type", - [DW_TAG_namespace] = "namespace", - [DW_TAG_imported_module] = "imported_module", - [DW_TAG_unspecified_type] = "unspecified_type", - [DW_TAG_partial_unit] = "partial_unit", - [DW_TAG_imported_unit] = "imported_unit", - [DW_TAG_mutable_type] = "mutable_type", - [DW_TAG_condition] = "condition", - [DW_TAG_shared_type] = "shared_type", - [DW_TAG_type_unit] = "type_unit", - [DW_TAG_rvalue_reference_type] = "rvalue_reference_type", - [DW_TAG_template_alias] = "template_alias", - }; - const unsigned int nknown_tags = (sizeof (known_tags) - / sizeof (known_tags[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (tag < nknown_tags)) - result = known_tags[tag]; - - if (unlikely (result == NULL)) - /* There are a few known extensions. */ - switch (tag) - { - case DW_TAG_MIPS_loop: - result = "MIPS_loop"; - break; - - case DW_TAG_format_label: - result = "format_label"; - break; - - case DW_TAG_function_template: - result = "function_template"; - break; - - case DW_TAG_class_template: - result = "class_template"; - break; - - case DW_TAG_GNU_BINCL: - result = "GNU_BINCL"; - break; - - case DW_TAG_GNU_EINCL: - result = "GNU_EINCL"; - break; - - case DW_TAG_GNU_template_template_param: - result = "GNU_template_template_param"; - break; - - case DW_TAG_GNU_template_parameter_pack: - result = "GNU_template_parameter_pack"; - break; - - case DW_TAG_GNU_formal_parameter_pack: - result = "GNU_formal_parameter_pack"; - break; - - case DW_TAG_GNU_call_site: - result = "GNU_call_site"; - break; - - case DW_TAG_GNU_call_site_parameter: - result = "GNU_call_site_parameter"; - break; - - default: - if (tag < DW_TAG_lo_user) - snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag); - else - snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag); - result = buf; - break; - } - - return result; + switch (tag) + { +#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_TAG +#undef ONE_KNOWN_DW_TAG + default: + return NULL; + } } static const char * dwarf_attr_string (unsigned int attrnum) { - static const char *const known_attrs[] = - { - [DW_AT_sibling] = "sibling", - [DW_AT_location] = "location", - [DW_AT_name] = "name", - [DW_AT_ordering] = "ordering", - [DW_AT_subscr_data] = "subscr_data", - [DW_AT_byte_size] = "byte_size", - [DW_AT_bit_offset] = "bit_offset", - [DW_AT_bit_size] = "bit_size", - [DW_AT_element_list] = "element_list", - [DW_AT_stmt_list] = "stmt_list", - [DW_AT_low_pc] = "low_pc", - [DW_AT_high_pc] = "high_pc", - [DW_AT_language] = "language", - [DW_AT_member] = "member", - [DW_AT_discr] = "discr", - [DW_AT_discr_value] = "discr_value", - [DW_AT_visibility] = "visibility", - [DW_AT_import] = "import", - [DW_AT_string_length] = "string_length", - [DW_AT_common_reference] = "common_reference", - [DW_AT_comp_dir] = "comp_dir", - [DW_AT_const_value] = "const_value", - [DW_AT_containing_type] = "containing_type", - [DW_AT_default_value] = "default_value", - [DW_AT_inline] = "inline", - [DW_AT_is_optional] = "is_optional", - [DW_AT_lower_bound] = "lower_bound", - [DW_AT_producer] = "producer", - [DW_AT_prototyped] = "prototyped", - [DW_AT_return_addr] = "return_addr", - [DW_AT_start_scope] = "start_scope", - [DW_AT_bit_stride] = "bit_stride", - [DW_AT_upper_bound] = "upper_bound", - [DW_AT_abstract_origin] = "abstract_origin", - [DW_AT_accessibility] = "accessibility", - [DW_AT_address_class] = "address_class", - [DW_AT_artificial] = "artificial", - [DW_AT_base_types] = "base_types", - [DW_AT_calling_convention] = "calling_convention", - [DW_AT_count] = "count", - [DW_AT_data_member_location] = "data_member_location", - [DW_AT_decl_column] = "decl_column", - [DW_AT_decl_file] = "decl_file", - [DW_AT_decl_line] = "decl_line", - [DW_AT_declaration] = "declaration", - [DW_AT_discr_list] = "discr_list", - [DW_AT_encoding] = "encoding", - [DW_AT_external] = "external", - [DW_AT_frame_base] = "frame_base", - [DW_AT_friend] = "friend", - [DW_AT_identifier_case] = "identifier_case", - [DW_AT_macro_info] = "macro_info", - [DW_AT_namelist_item] = "namelist_item", - [DW_AT_priority] = "priority", - [DW_AT_segment] = "segment", - [DW_AT_specification] = "specification", - [DW_AT_static_link] = "static_link", - [DW_AT_type] = "type", - [DW_AT_use_location] = "use_location", - [DW_AT_variable_parameter] = "variable_parameter", - [DW_AT_virtuality] = "virtuality", - [DW_AT_vtable_elem_location] = "vtable_elem_location", - [DW_AT_allocated] = "allocated", - [DW_AT_associated] = "associated", - [DW_AT_data_location] = "data_location", - [DW_AT_byte_stride] = "byte_stride", - [DW_AT_entry_pc] = "entry_pc", - [DW_AT_use_UTF8] = "use_UTF8", - [DW_AT_extension] = "extension", - [DW_AT_ranges] = "ranges", - [DW_AT_trampoline] = "trampoline", - [DW_AT_call_column] = "call_column", - [DW_AT_call_file] = "call_file", - [DW_AT_call_line] = "call_line", - [DW_AT_description] = "description", - [DW_AT_binary_scale] = "binary_scale", - [DW_AT_decimal_scale] = "decimal_scale", - [DW_AT_small] = "small", - [DW_AT_decimal_sign] = "decimal_sign", - [DW_AT_digit_count] = "digit_count", - [DW_AT_picture_string] = "picture_string", - [DW_AT_mutable] = "mutable", - [DW_AT_threads_scaled] = "threads_scaled", - [DW_AT_explicit] = "explicit", - [DW_AT_object_pointer] = "object_pointer", - [DW_AT_endianity] = "endianity", - [DW_AT_elemental] = "elemental", - [DW_AT_pure] = "pure", - [DW_AT_recursive] = "recursive", - [DW_AT_signature] = "signature", - [DW_AT_main_subprogram] = "main_subprogram", - [DW_AT_data_bit_offset] = "data_bit_offset", - [DW_AT_const_expr] = "const_expr", - [DW_AT_enum_class] = "enum_class", - [DW_AT_linkage_name] = "linkage_name", - }; - const unsigned int nknown_attrs = (sizeof (known_attrs) - / sizeof (known_attrs[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (attrnum < nknown_attrs)) - result = known_attrs[attrnum]; - - if (unlikely (result == NULL)) - /* There are a few known extensions. */ - switch (attrnum) - { - case DW_AT_MIPS_fde: - result = "MIPS_fde"; - break; - - case DW_AT_MIPS_loop_begin: - result = "MIPS_loop_begin"; - break; - - case DW_AT_MIPS_tail_loop_begin: - result = "MIPS_tail_loop_begin"; - break; - - case DW_AT_MIPS_epilog_begin: - result = "MIPS_epilog_begin"; - break; - - case DW_AT_MIPS_loop_unroll_factor: - result = "MIPS_loop_unroll_factor"; - break; - - case DW_AT_MIPS_software_pipeline_depth: - result = "MIPS_software_pipeline_depth"; - break; - - case DW_AT_MIPS_linkage_name: - result = "MIPS_linkage_name"; - break; - - case DW_AT_MIPS_stride: - result = "MIPS_stride"; - break; - - case DW_AT_MIPS_abstract_name: - result = "MIPS_abstract_name"; - break; - - case DW_AT_MIPS_clone_origin: - result = "MIPS_clone_origin"; - break; - - case DW_AT_MIPS_has_inlines: - result = "MIPS_has_inlines"; - break; - - case DW_AT_MIPS_stride_byte: - result = "MIPS_stride_byte"; - break; - - case DW_AT_MIPS_stride_elem: - result = "MIPS_stride_elem"; - break; - - case DW_AT_MIPS_ptr_dopetype: - result = "MIPS_ptr_dopetype"; - break; - - case DW_AT_MIPS_allocatable_dopetype: - result = "MIPS_allocatable_dopetype"; - break; - - case DW_AT_MIPS_assumed_shape_dopetype: - result = "MIPS_assumed_shape_dopetype"; - break; - - case DW_AT_MIPS_assumed_size: - result = "MIPS_assumed_size"; - break; - - case DW_AT_sf_names: - result = "sf_names"; - break; - - case DW_AT_src_info: - result = "src_info"; - break; - - case DW_AT_mac_info: - result = "mac_info"; - break; - - case DW_AT_src_coords: - result = "src_coords"; - break; - - case DW_AT_body_begin: - result = "body_begin"; - break; - - case DW_AT_body_end: - result = "body_end"; - break; - - case DW_AT_GNU_vector: - result = "GNU_vector"; - break; - - case DW_AT_GNU_guarded_by: - result = "GNU_guarded_by"; - break; - - case DW_AT_GNU_pt_guarded_by: - result = "GNU_pt_guarded_by"; - break; - - case DW_AT_GNU_guarded: - result = "GNU_guarded"; - break; - - case DW_AT_GNU_pt_guarded: - result = "GNU_pt_guarded"; - break; - - case DW_AT_GNU_locks_excluded: - result = "GNU_locks_excluded"; - break; - - case DW_AT_GNU_exclusive_locks_required: - result = "GNU_exclusive_locks_required"; - break; - - case DW_AT_GNU_shared_locks_required: - result = "GNU_shared_locks_required"; - break; - - case DW_AT_GNU_odr_signature: - result = "GNU_odr_signature"; - break; - - case DW_AT_GNU_template_name: - result = "GNU_template_name"; - break; - - case DW_AT_GNU_call_site_value: - result = "GNU_call_site_value"; - break; - - case DW_AT_GNU_call_site_data_value: - result = "GNU_call_site_data_value"; - break; - - case DW_AT_GNU_call_site_target: - result = "GNU_call_site_target"; - break; - - case DW_AT_GNU_call_site_target_clobbered: - result = "GNU_call_site_target_clobbered"; - break; - - case DW_AT_GNU_tail_call: - result = "GNU_tail_call"; - break; - - case DW_AT_GNU_all_tail_call_sites: - result = "GNU_all_tail_call_sites"; - break; - - case DW_AT_GNU_all_call_sites: - result = "GNU_all_call_sites"; - break; - - case DW_AT_GNU_all_source_call_sites: - result = "GNU_all_source_call_sites"; - break; - - default: - if (attrnum < DW_AT_lo_user) - snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"), - attrnum); - else - snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"), - attrnum); - result = buf; - break; - } - - return result; + switch (attrnum) + { +#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_AT +#undef ONE_KNOWN_DW_AT + default: + return NULL; + } } static const char * dwarf_form_string (unsigned int form) { - static const char *const known_forms[] = - { - [DW_FORM_addr] = "addr", - [DW_FORM_block2] = "block2", - [DW_FORM_block4] = "block4", - [DW_FORM_data2] = "data2", - [DW_FORM_data4] = "data4", - [DW_FORM_data8] = "data8", - [DW_FORM_string] = "string", - [DW_FORM_block] = "block", - [DW_FORM_block1] = "block1", - [DW_FORM_data1] = "data1", - [DW_FORM_flag] = "flag", - [DW_FORM_sdata] = "sdata", - [DW_FORM_strp] = "strp", - [DW_FORM_udata] = "udata", - [DW_FORM_ref_addr] = "ref_addr", - [DW_FORM_ref1] = "ref1", - [DW_FORM_ref2] = "ref2", - [DW_FORM_ref4] = "ref4", - [DW_FORM_ref8] = "ref8", - [DW_FORM_ref_udata] = "ref_udata", - [DW_FORM_indirect] = "indirect", - [DW_FORM_sec_offset] = "sec_offset", - [DW_FORM_exprloc] = "exprloc", - [DW_FORM_flag_present] = "flag_present", - [DW_FORM_ref_sig8] = "ref_sig8", - }; - const unsigned int nknown_forms = (sizeof (known_forms) - / sizeof (known_forms[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (form < nknown_forms)) - result = known_forms[form]; - - if (unlikely (result == NULL)) + switch (form) { - snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64), - (uint64_t) form); - result = buf; +#define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE) +#define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_FORM +#undef ONE_KNOWN_DW_FORM +#undef ONE_KNOWN_DW_FORM_DESC + default: + return NULL; } - - return result; } static const char * dwarf_lang_string (unsigned int lang) { - static const char *const known[] = - { - [DW_LANG_C89] = "ISO C89", - [DW_LANG_C] = "C", - [DW_LANG_Ada83] = "Ada83", - [DW_LANG_C_plus_plus] = "C++", - [DW_LANG_Cobol74] = "Cobol74", - [DW_LANG_Cobol85] = "Cobol85", - [DW_LANG_Fortran77] = "Fortran77", - [DW_LANG_Fortran90] = "Fortran90", - [DW_LANG_Pascal83] = "Pascal83", - [DW_LANG_Modula2] = "Modula2", - [DW_LANG_Java] = "Java", - [DW_LANG_C99] = "ISO C99", - [DW_LANG_Ada95] = "Ada95", - [DW_LANG_Fortran95] = "Fortran95", - [DW_LANG_PL1] = "PL1", - [DW_LANG_Objc] = "Objective C", - [DW_LANG_ObjC_plus_plus] = "Objective C++", - [DW_LANG_UPC] = "UPC", - [DW_LANG_D] = "D", - }; - - if (likely (lang < sizeof (known) / sizeof (known[0]))) - return known[lang]; - else if (lang == DW_LANG_Mips_Assembler) - /* This language tag is used for assembler in general. */ - return "Assembler"; - - if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user) + switch (lang) { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user); - return buf; +#define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME; + ALL_KNOWN_DW_LANG +#undef ONE_KNOWN_DW_LANG_DESC + default: + return NULL; } - - return "???"; } @@ -3711,16 +3624,15 @@ dwarf_inline_string (unsigned int code) { static const char *const known[] = { - [DW_INL_not_inlined] = "not_inlined", - [DW_INL_inlined] = "inlined", - [DW_INL_declared_not_inlined] = "declared_not_inlined", - [DW_INL_declared_inlined] = "declared_inlined" +#define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_INL +#undef ONE_KNOWN_DW_INL }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3729,35 +3641,15 @@ dwarf_encoding_string (unsigned int code) { static const char *const known[] = { - [DW_ATE_void] = "void", - [DW_ATE_address] = "address", - [DW_ATE_boolean] = "boolean", - [DW_ATE_complex_float] = "complex_float", - [DW_ATE_float] = "float", - [DW_ATE_signed] = "signed", - [DW_ATE_signed_char] = "signed_char", - [DW_ATE_unsigned] = "unsigned", - [DW_ATE_unsigned_char] = "unsigned_char", - [DW_ATE_imaginary_float] = "imaginary_float", - [DW_ATE_packed_decimal] = "packed_decimal", - [DW_ATE_numeric_string] = "numeric_string", - [DW_ATE_edited] = "edited", - [DW_ATE_signed_fixed] = "signed_fixed", - [DW_ATE_unsigned_fixed] = "unsigned_fixed", - [DW_ATE_decimal_float] = "decimal_float", +#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ATE +#undef ONE_KNOWN_DW_ATE }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user) - { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user); - return buf; - } - - return "???"; + return NULL; } @@ -3766,15 +3658,15 @@ dwarf_access_string (unsigned int code) { static const char *const known[] = { - [DW_ACCESS_public] = "public", - [DW_ACCESS_protected] = "protected", - [DW_ACCESS_private] = "private" +#define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ACCESS +#undef ONE_KNOWN_DW_ACCESS }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3783,15 +3675,15 @@ dwarf_visibility_string (unsigned int code) { static const char *const known[] = { - [DW_VIS_local] = "local", - [DW_VIS_exported] = "exported", - [DW_VIS_qualified] = "qualified" +#define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_VIS +#undef ONE_KNOWN_DW_VIS }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3800,15 +3692,15 @@ dwarf_virtuality_string (unsigned int code) { static const char *const known[] = { - [DW_VIRTUALITY_none] = "none", - [DW_VIRTUALITY_virtual] = "virtual", - [DW_VIRTUALITY_pure_virtual] = "pure_virtual" +#define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_VIRTUALITY +#undef ONE_KNOWN_DW_VIRTUALITY }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3817,16 +3709,15 @@ dwarf_identifier_case_string (unsigned int code) { static const char *const known[] = { - [DW_ID_case_sensitive] = "sensitive", - [DW_ID_up_case] = "up_case", - [DW_ID_down_case] = "down_case", - [DW_ID_case_insensitive] = "insensitive" +#define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ID +#undef ONE_KNOWN_DW_ID }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3835,22 +3726,15 @@ dwarf_calling_convention_string (unsigned int code) { static const char *const known[] = { - [DW_CC_normal] = "normal", - [DW_CC_program] = "program", - [DW_CC_nocall] = "nocall", +#define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_CC +#undef ONE_KNOWN_DW_CC }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - if (code >= DW_CC_lo_user && code <= DW_CC_hi_user) - { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user); - return buf; - } - - return "???"; + return NULL; } @@ -3859,14 +3743,15 @@ dwarf_ordering_string (unsigned int code) { static const char *const known[] = { - [DW_ORD_row_major] = "row_major", - [DW_ORD_col_major] = "col_major" +#define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ORD +#undef ONE_KNOWN_DW_ORD }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3875,17 +3760,171 @@ dwarf_discr_list_string (unsigned int code) { static const char *const known[] = { - [DW_DSC_label] = "label", - [DW_DSC_range] = "range" +#define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_DSC +#undef ONE_KNOWN_DW_DSC + }; + + if (likely (code < sizeof (known) / sizeof (known[0]))) + return known[code]; + + return NULL; +} + + +static const char * +dwarf_locexpr_opcode_string (unsigned int code) +{ + static const char *const known[] = + { + /* Normally we can't affort building huge table of 64K entries, + most of them zero, just because there are a couple defined + values at the far end. In case of opcodes, it's OK. */ +#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE) +#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_OP +#undef ONE_KNOWN_DW_OP +#undef ONE_KNOWN_DW_OP_DESC }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; + return NULL; +} + + +/* Used by all dwarf_foo_name functions. */ +static const char * +string_or_unknown (const char *known, unsigned int code, + unsigned int lo_user, unsigned int hi_user, + bool print_unknown_num) +{ + static char unknown_buf[20]; + + if (likely (known != NULL)) + return known; + + if (lo_user != 0 && code >= lo_user && code <= hi_user) + { + snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x", + code - lo_user); + return unknown_buf; + } + + if (print_unknown_num) + { + snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code); + return unknown_buf; + } + return "???"; } +static const char * +dwarf_tag_name (unsigned int tag) +{ + const char *ret = dwarf_tag_string (tag); + return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true); +} + +static const char * +dwarf_attr_name (unsigned int attr) +{ + const char *ret = dwarf_attr_string (attr); + return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true); +} + + +static const char * +dwarf_form_name (unsigned int form) +{ + const char *ret = dwarf_form_string (form); + return string_or_unknown (ret, form, 0, 0, true); +} + + +static const char * +dwarf_lang_name (unsigned int lang) +{ + const char *ret = dwarf_lang_string (lang); + return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false); +} + + +static const char * +dwarf_inline_name (unsigned int code) +{ + const char *ret = dwarf_inline_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_encoding_name (unsigned int code) +{ + const char *ret = dwarf_encoding_string (code); + return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false); +} + + +static const char * +dwarf_access_name (unsigned int code) +{ + const char *ret = dwarf_access_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_visibility_name (unsigned int code) +{ + const char *ret = dwarf_visibility_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_virtuality_name (unsigned int code) +{ + const char *ret = dwarf_virtuality_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_identifier_case_name (unsigned int code) +{ + const char *ret = dwarf_identifier_case_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_calling_convention_name (unsigned int code) +{ + const char *ret = dwarf_calling_convention_string (code); + return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false); +} + + +static const char * +dwarf_ordering_name (unsigned int code) +{ + const char *ret = dwarf_ordering_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_discr_list_name (unsigned int code) +{ + const char *ret = dwarf_discr_list_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + static void print_block (size_t n, const void *block) { @@ -3905,175 +3944,10 @@ print_block (size_t n, const void *block) static void print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, unsigned int vers, unsigned int addrsize, unsigned int offset_size, - Dwarf_Word len, const unsigned char *data) + struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data) { const unsigned int ref_size = vers < 3 ? addrsize : offset_size; - static const char *const known[] = - { - [DW_OP_addr] = "addr", - [DW_OP_deref] = "deref", - [DW_OP_const1u] = "const1u", - [DW_OP_const1s] = "const1s", - [DW_OP_const2u] = "const2u", - [DW_OP_const2s] = "const2s", - [DW_OP_const4u] = "const4u", - [DW_OP_const4s] = "const4s", - [DW_OP_const8u] = "const8u", - [DW_OP_const8s] = "const8s", - [DW_OP_constu] = "constu", - [DW_OP_consts] = "consts", - [DW_OP_dup] = "dup", - [DW_OP_drop] = "drop", - [DW_OP_over] = "over", - [DW_OP_pick] = "pick", - [DW_OP_swap] = "swap", - [DW_OP_rot] = "rot", - [DW_OP_xderef] = "xderef", - [DW_OP_abs] = "abs", - [DW_OP_and] = "and", - [DW_OP_div] = "div", - [DW_OP_minus] = "minus", - [DW_OP_mod] = "mod", - [DW_OP_mul] = "mul", - [DW_OP_neg] = "neg", - [DW_OP_not] = "not", - [DW_OP_or] = "or", - [DW_OP_plus] = "plus", - [DW_OP_plus_uconst] = "plus_uconst", - [DW_OP_shl] = "shl", - [DW_OP_shr] = "shr", - [DW_OP_shra] = "shra", - [DW_OP_xor] = "xor", - [DW_OP_bra] = "bra", - [DW_OP_eq] = "eq", - [DW_OP_ge] = "ge", - [DW_OP_gt] = "gt", - [DW_OP_le] = "le", - [DW_OP_lt] = "lt", - [DW_OP_ne] = "ne", - [DW_OP_skip] = "skip", - [DW_OP_lit0] = "lit0", - [DW_OP_lit1] = "lit1", - [DW_OP_lit2] = "lit2", - [DW_OP_lit3] = "lit3", - [DW_OP_lit4] = "lit4", - [DW_OP_lit5] = "lit5", - [DW_OP_lit6] = "lit6", - [DW_OP_lit7] = "lit7", - [DW_OP_lit8] = "lit8", - [DW_OP_lit9] = "lit9", - [DW_OP_lit10] = "lit10", - [DW_OP_lit11] = "lit11", - [DW_OP_lit12] = "lit12", - [DW_OP_lit13] = "lit13", - [DW_OP_lit14] = "lit14", - [DW_OP_lit15] = "lit15", - [DW_OP_lit16] = "lit16", - [DW_OP_lit17] = "lit17", - [DW_OP_lit18] = "lit18", - [DW_OP_lit19] = "lit19", - [DW_OP_lit20] = "lit20", - [DW_OP_lit21] = "lit21", - [DW_OP_lit22] = "lit22", - [DW_OP_lit23] = "lit23", - [DW_OP_lit24] = "lit24", - [DW_OP_lit25] = "lit25", - [DW_OP_lit26] = "lit26", - [DW_OP_lit27] = "lit27", - [DW_OP_lit28] = "lit28", - [DW_OP_lit29] = "lit29", - [DW_OP_lit30] = "lit30", - [DW_OP_lit31] = "lit31", - [DW_OP_reg0] = "reg0", - [DW_OP_reg1] = "reg1", - [DW_OP_reg2] = "reg2", - [DW_OP_reg3] = "reg3", - [DW_OP_reg4] = "reg4", - [DW_OP_reg5] = "reg5", - [DW_OP_reg6] = "reg6", - [DW_OP_reg7] = "reg7", - [DW_OP_reg8] = "reg8", - [DW_OP_reg9] = "reg9", - [DW_OP_reg10] = "reg10", - [DW_OP_reg11] = "reg11", - [DW_OP_reg12] = "reg12", - [DW_OP_reg13] = "reg13", - [DW_OP_reg14] = "reg14", - [DW_OP_reg15] = "reg15", - [DW_OP_reg16] = "reg16", - [DW_OP_reg17] = "reg17", - [DW_OP_reg18] = "reg18", - [DW_OP_reg19] = "reg19", - [DW_OP_reg20] = "reg20", - [DW_OP_reg21] = "reg21", - [DW_OP_reg22] = "reg22", - [DW_OP_reg23] = "reg23", - [DW_OP_reg24] = "reg24", - [DW_OP_reg25] = "reg25", - [DW_OP_reg26] = "reg26", - [DW_OP_reg27] = "reg27", - [DW_OP_reg28] = "reg28", - [DW_OP_reg29] = "reg29", - [DW_OP_reg30] = "reg30", - [DW_OP_reg31] = "reg31", - [DW_OP_breg0] = "breg0", - [DW_OP_breg1] = "breg1", - [DW_OP_breg2] = "breg2", - [DW_OP_breg3] = "breg3", - [DW_OP_breg4] = "breg4", - [DW_OP_breg5] = "breg5", - [DW_OP_breg6] = "breg6", - [DW_OP_breg7] = "breg7", - [DW_OP_breg8] = "breg8", - [DW_OP_breg9] = "breg9", - [DW_OP_breg10] = "breg10", - [DW_OP_breg11] = "breg11", - [DW_OP_breg12] = "breg12", - [DW_OP_breg13] = "breg13", - [DW_OP_breg14] = "breg14", - [DW_OP_breg15] = "breg15", - [DW_OP_breg16] = "breg16", - [DW_OP_breg17] = "breg17", - [DW_OP_breg18] = "breg18", - [DW_OP_breg19] = "breg19", - [DW_OP_breg20] = "breg20", - [DW_OP_breg21] = "breg21", - [DW_OP_breg22] = "breg22", - [DW_OP_breg23] = "breg23", - [DW_OP_breg24] = "breg24", - [DW_OP_breg25] = "breg25", - [DW_OP_breg26] = "breg26", - [DW_OP_breg27] = "breg27", - [DW_OP_breg28] = "breg28", - [DW_OP_breg29] = "breg29", - [DW_OP_breg30] = "breg30", - [DW_OP_breg31] = "breg31", - [DW_OP_regx] = "regx", - [DW_OP_fbreg] = "fbreg", - [DW_OP_bregx] = "bregx", - [DW_OP_piece] = "piece", - [DW_OP_deref_size] = "deref_size", - [DW_OP_xderef_size] = "xderef_size", - [DW_OP_nop] = "nop", - [DW_OP_push_object_address] = "push_object_address", - [DW_OP_call2] = "call2", - [DW_OP_call4] = "call4", - [DW_OP_call_ref] = "call_ref", - [DW_OP_form_tls_address] = "form_tls_address", - [DW_OP_call_frame_cfa] = "call_frame_cfa", - [DW_OP_bit_piece] = "bit_piece", - [DW_OP_implicit_value] = "implicit_value", - [DW_OP_stack_value] = "stack_value", - [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer", - [DW_OP_GNU_entry_value] = "GNU_entry_value", - [DW_OP_GNU_const_type] = "GNU_const_type", - [DW_OP_GNU_regval_type] = "GNU_regval_type", - [DW_OP_GNU_deref_type] = "GNU_deref_type", - [DW_OP_GNU_convert] = "GNU_convert", - [DW_OP_GNU_reinterpret] = "GNU_reinterpret", - }; - if (len == 0) { printf ("%*s(empty)\n", indent, ""); @@ -4088,6 +3962,17 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, { uint_fast8_t op = *data++; + const char *op_name = dwarf_locexpr_opcode_string (op); + if (unlikely (op_name == NULL)) + { + static char buf[20]; + if (op >= DW_OP_lo_user) + snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user); + else + snprintf (buf, sizeof buf, "??? (%#x)", op); + op_name = buf; + } + switch (op) { case DW_OP_addr:; @@ -4096,17 +3981,16 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (addrsize); if (addrsize == 4) addr = read_4ubyte_unaligned (dbg, data); + else if (addrsize == 8) + addr = read_8ubyte_unaligned (dbg, data); else - { - assert (addrsize == 8); - addr = read_8ubyte_unaligned (dbg, data); - } + goto invalid; data += addrsize; CONSUME (addrsize); - char *a = format_dwarf_addr (dwflmod, 0, addr); + char *a = format_dwarf_addr (dwflmod, 0, addr, addr); printf ("%*s[%4" PRIuMAX "] %s %s\n", - indent, "", (uintmax_t) offset, known[op], a); + indent, "", (uintmax_t) offset, op_name, a); free (a); offset += 1 + addrsize; @@ -4114,20 +3998,19 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call_ref: /* Offset operand. */ + if (ref_size != 4 && ref_size != 8) + goto invalid; /* Cannot be used in CFA. */ NEED (ref_size); if (ref_size == 4) addr = read_4ubyte_unaligned (dbg, data); else - { - assert (ref_size == 8); - addr = read_8ubyte_unaligned (dbg, data); - } + addr = read_8ubyte_unaligned (dbg, data); data += ref_size; CONSUME (ref_size); printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n", indent, "", (uintmax_t) offset, - known[op], (uintmax_t) addr); + op_name, (uintmax_t) addr); offset += 1 + ref_size; break; @@ -4139,7 +4022,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n", indent, "", (uintmax_t) offset, - known[op], *((uint8_t *) data)); + op_name, *((uint8_t *) data)); ++data; --len; offset += 2; @@ -4150,7 +4033,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n", indent, "", (uintmax_t) offset, - known[op], read_2ubyte_unaligned (dbg, data)); + op_name, read_2ubyte_unaligned (dbg, data)); CONSUME (2); data += 2; offset += 3; @@ -4161,7 +4044,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n", indent, "", (uintmax_t) offset, - known[op], read_4ubyte_unaligned (dbg, data)); + op_name, read_4ubyte_unaligned (dbg, data)); CONSUME (4); data += 4; offset += 5; @@ -4172,7 +4055,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n", indent, "", (uintmax_t) offset, - known[op], read_8ubyte_unaligned (dbg, data)); + op_name, (uint64_t) read_8ubyte_unaligned (dbg, data)); CONSUME (8); data += 8; offset += 9; @@ -4183,7 +4066,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n", indent, "", (uintmax_t) offset, - known[op], *((int8_t *) data)); + op_name, *((int8_t *) data)); ++data; --len; offset += 2; @@ -4194,7 +4077,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n", indent, "", (uintmax_t) offset, - known[op], read_2sbyte_unaligned (dbg, data)); + op_name, read_2sbyte_unaligned (dbg, data)); CONSUME (2); data += 2; offset += 3; @@ -4205,7 +4088,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n", indent, "", (uintmax_t) offset, - known[op], read_4sbyte_unaligned (dbg, data)); + op_name, read_4sbyte_unaligned (dbg, data)); CONSUME (4); data += 4; offset += 5; @@ -4216,7 +4099,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n", indent, "", (uintmax_t) offset, - known[op], read_8sbyte_unaligned (dbg, data)); + op_name, read_8sbyte_unaligned (dbg, data)); CONSUME (8); data += 8; offset += 9; @@ -4229,9 +4112,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, const unsigned char *start = data; uint64_t uleb; NEED (1); - get_uleb128 (uleb, data); /* XXX check overrun */ + get_uleb128 (uleb, data, data + len); printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4239,11 +4122,12 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_bit_piece: start = data; uint64_t uleb2; - NEED (2); - get_uleb128 (uleb, data); /* XXX check overrun */ - get_uleb128 (uleb2, data); /* XXX check overrun */ + NEED (1); + get_uleb128 (uleb, data, data + len); + NEED (1); + get_uleb128 (uleb2, data, data + len); printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, uleb2); + indent, "", (uintmax_t) offset, op_name, uleb, uleb2); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4254,20 +4138,21 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, start = data; int64_t sleb; NEED (1); - get_sleb128 (sleb, data); /* XXX check overrun */ + get_sleb128 (sleb, data, data + len); printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n", - indent, "", (uintmax_t) offset, known[op], sleb); + indent, "", (uintmax_t) offset, op_name, sleb); CONSUME (data - start); offset += 1 + (data - start); break; case DW_OP_bregx: start = data; - NEED (2); - get_uleb128 (uleb, data); /* XXX check overrun */ - get_sleb128 (sleb, data); /* XXX check overrun */ + NEED (1); + get_uleb128 (uleb, data, data + len); + NEED (1); + get_sleb128 (sleb, data, data + len); printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, sleb); + indent, "", (uintmax_t) offset, op_name, uleb, sleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4275,7 +4160,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call2: NEED (2); printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n", - indent, "", (uintmax_t) offset, known[op], + indent, "", (uintmax_t) offset, op_name, read_2ubyte_unaligned (dbg, data)); CONSUME (2); offset += 3; @@ -4284,7 +4169,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call4: NEED (4); printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n", - indent, "", (uintmax_t) offset, known[op], + indent, "", (uintmax_t) offset, op_name, read_4ubyte_unaligned (dbg, data)); CONSUME (4); offset += 5; @@ -4294,8 +4179,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_bra: NEED (2); printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n", - indent, "", (uintmax_t) offset, known[op], - (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data))); + indent, "", (uintmax_t) offset, op_name, + (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3)); CONSUME (2); data += 2; offset += 3; @@ -4304,9 +4189,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_implicit_value: start = data; NEED (1); - get_uleb128 (uleb, data); /* XXX check overrun */ + get_uleb128 (uleb, data, data + len); printf ("%*s[%4" PRIuMAX "] %s: ", - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); NEED (uleb); print_block (uleb, data); data += uleb; @@ -4317,21 +4202,21 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_GNU_implicit_pointer: /* DIE offset operand. */ start = data; - NEED (ref_size + 1); + NEED (ref_size); + if (ref_size != 4 && ref_size != 8) + goto invalid; /* Cannot be used in CFA. */ if (ref_size == 4) addr = read_4ubyte_unaligned (dbg, data); else - { - assert (ref_size == 8); - addr = read_8ubyte_unaligned (dbg, data); - } + addr = read_8ubyte_unaligned (dbg, data); data += ref_size; /* Byte offset operand. */ - get_sleb128 (sleb, data); /* XXX check overrun */ + NEED (1); + get_sleb128 (sleb, data, data + len); - printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n", + printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n", indent, "", (intmax_t) offset, - known[op], (uintmax_t) addr, sleb); + op_name, (uintmax_t) addr, sleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4340,26 +4225,30 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, /* Size plus expression block. */ start = data; NEED (1); - get_uleb128 (uleb, data); /* XXX check overrun */ + get_uleb128 (uleb, data, data + len); printf ("%*s[%4" PRIuMAX "] %s:\n", - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); NEED (uleb); print_ops (dwflmod, dbg, indent + 6, indent + 6, vers, - addrsize, offset_size, uleb, data); + addrsize, offset_size, cu, uleb, data); data += uleb; CONSUME (data - start); offset += 1 + (data - start); break; case DW_OP_GNU_const_type: - /* DIE offset, size plus block. */ + /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte + unsigned size plus block. */ start = data; - NEED (2); - get_uleb128 (uleb, data); /* XXX check overrun */ + NEED (1); + get_uleb128 (uleb, data, data + len); + if (! print_unresolved_addresses && cu != NULL) + uleb += cu->start; + NEED (1); uint8_t usize = *(uint8_t *) data++; NEED (usize); printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); print_block (usize, data); data += usize; CONSUME (data - start); @@ -4367,47 +4256,71 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, break; case DW_OP_GNU_regval_type: + /* uleb128 register number, uleb128 CU relative + DW_TAG_base_type DIE offset. */ start = data; - NEED (2); - get_uleb128 (uleb, data); /* XXX check overrun */ - get_uleb128 (uleb2, data); /* XXX check overrun */ - printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, uleb2); + NEED (1); + get_uleb128 (uleb, data, data + len); + NEED (1); + get_uleb128 (uleb2, data, data + len); + if (! print_unresolved_addresses && cu != NULL) + uleb2 += cu->start; + printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n", + indent, "", (uintmax_t) offset, op_name, uleb, uleb2); CONSUME (data - start); offset += 1 + (data - start); break; case DW_OP_GNU_deref_type: + /* 1-byte unsigned size of value, uleb128 CU relative + DW_TAG_base_type DIE offset. */ start = data; - NEED (2); + NEED (1); usize = *(uint8_t *) data++; - get_uleb128 (uleb, data); /* XXX check overrun */ + NEED (1); + get_uleb128 (uleb, data, data + len); + if (! print_unresolved_addresses && cu != NULL) + uleb += cu->start; printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n", indent, "", (uintmax_t) offset, - known[op], usize, uleb); + op_name, usize, uleb); CONSUME (data - start); offset += 1 + (data - start); break; case DW_OP_GNU_convert: case DW_OP_GNU_reinterpret: + /* uleb128 CU relative offset to DW_TAG_base_type, or zero + for conversion to untyped. */ start = data; NEED (1); - get_uleb128 (uleb, data); /* XXX check overrun */ + get_uleb128 (uleb, data, data + len); + if (uleb != 0 && ! print_unresolved_addresses && cu != NULL) + uleb += cu->start; printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); CONSUME (data - start); offset += 1 + (data - start); break; + case DW_OP_GNU_parameter_ref: + /* 4 byte CU relative reference to the abstract optimized away + DW_TAG_formal_parameter. */ + NEED (4); + uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data); + if (! print_unresolved_addresses && cu != NULL) + param_off += cu->start; + printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n", + indent, "", (uintmax_t) offset, op_name, param_off); + CONSUME (4); + data += 4; + offset += 5; + break; + default: /* No Operand. */ - if (op < sizeof known / sizeof known[0] && known[op] != NULL) - printf ("%*s[%4" PRIuMAX "] %s\n", - indent, "", (uintmax_t) offset, known[op]); - else - printf ("%*s[%4" PRIuMAX "] %#x\n", - indent, "", (uintmax_t) offset, op); + printf ("%*s[%4" PRIuMAX "] %s\n", + indent, "", (uintmax_t) offset, op_name); ++offset; break; } @@ -4417,7 +4330,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, invalid: printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"), - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); break; } } @@ -4429,11 +4342,32 @@ struct listptr bool addr64:1; bool dwarf64:1; bool warned:1; + struct Dwarf_CU *cu; }; #define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4) #define listptr_address_size(p) ((p)->addr64 ? 8 : 4) +static Dwarf_Addr +listptr_base (struct listptr *p) +{ + Dwarf_Addr base; + Dwarf_Die cu = CUDIE (p->cu); + /* Find the base address of the compilation unit. It will normally + be specified by DW_AT_low_pc. In DWARF-3 draft 4, the base + address could be overridden by DW_AT_entry_pc. It's been + removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for + compilation units with discontinuous ranges. */ + if (unlikely (dwarf_lowpc (&cu, &base) != 0)) + { + Dwarf_Attribute attr_mem; + if (dwarf_formaddr (dwarf_attr (&cu, DW_AT_entry_pc, &attr_mem), + &base) != 0) + base = 0; + } + return base; +} + static int compare_listptr (const void *a, const void *b, void *arg) { @@ -4462,6 +4396,13 @@ compare_listptr (const void *a, const void *b, void *arg) gettext ("%s %#" PRIx64 " used with different offset sizes"), name, (uint64_t) p1->offset); } + if (listptr_base (p1) != listptr_base (p2)) + { + p1->warned = p2->warned = true; + error (0, 0, + gettext ("%s %#" PRIx64 " used with different base addresses"), + name, (uint64_t) p1->offset); + } } return 0; @@ -4485,10 +4426,11 @@ reset_listptr (struct listptr_table *table) table->n = table->alloc = 0; } -static void +/* Returns false if offset doesn't fit. See struct listptr. */ +static bool notice_listptr (enum section_e section, struct listptr_table *table, uint_fast8_t address_size, uint_fast8_t offset_size, - Dwarf_Off offset) + struct Dwarf_CU *cu, Dwarf_Off offset) { if (print_debug_sections & section) { @@ -4508,10 +4450,17 @@ notice_listptr (enum section_e section, struct listptr_table *table, { .addr64 = address_size == 8, .dwarf64 = offset_size == 8, - .offset = offset + .offset = offset, + .cu = cu }; - assert (p->offset == offset); + + if (p->offset != offset) + { + table->n--; + return false; + } } + return true; } static void @@ -4525,7 +4474,8 @@ sort_listptr (struct listptr_table *table, const char *name) static bool skip_listptr_hole (struct listptr_table *table, size_t *idxp, uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep, - ptrdiff_t offset, unsigned char **readp, unsigned char *endp) + Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset, + unsigned char **readp, unsigned char *endp) { if (table->n == 0) return false; @@ -4556,6 +4506,10 @@ skip_listptr_hole (struct listptr_table *table, size_t *idxp, *address_sizep = listptr_address_size (p); if (offset_sizep != NULL) *offset_sizep = listptr_offset_size (p); + if (base != NULL) + *base = listptr_base (p); + if (cu != NULL) + *cu = p->cu; return false; } @@ -4566,13 +4520,16 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { + const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ? + dbg->sectiondata[IDX_debug_abbrev]->d_size : 0); + printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n" " [ Code]\n"), elf_ndxscn (scn), section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset); Dwarf_Off offset = 0; - while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size) + while (offset < sh_size) { printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"), offset); @@ -4607,7 +4564,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), ", children: %s, tag: %s\n"), code, (int64_t) offset, has_children ? gettext ("yes") : gettext ("no"), - dwarf_tag_string (tag)); + dwarf_tag_name (tag)); size_t cnt = 0; unsigned int name; @@ -4617,7 +4574,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), &name, &form, &enoffset) == 0) { printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n", - dwarf_attr_string (name), dwarf_form_string (form), + dwarf_attr_name (name), dwarf_form_name (form), (uint64_t) enoffset); ++cnt; @@ -4633,9 +4590,8 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), not have to know a bit about the structure of the section, libdwarf takes care of it. */ static void -print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, - GElf_Shdr *shdr, Dwarf *dbg) +print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr, Dwarf *dbg) { Dwarf_Aranges *aranges; size_t cnt; @@ -4646,6 +4602,16 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), return; } + GElf_Shdr glink_mem; + GElf_Shdr *glink; + glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem); + if (glink == NULL) + { + error (0, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + return; + } + printf (ngettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n", "\ @@ -4687,6 +4653,166 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } } + +/* Print content of DWARF .debug_aranges section. */ +static void +print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr, Dwarf *dbg) +{ + if (decodedaranges) + { + print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg); + return; + } + + Elf_Data *data = dbg->sectiondata[IDX_debug_aranges]; + + if (unlikely (data == NULL)) + { + error (0, 0, gettext ("cannot get .debug_aranges content: %s"), + elf_errmsg (-1)); + return; + } + + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + + const unsigned char *readp = data->d_buf; + const unsigned char *readendp = readp + data->d_size; + + while (readp < readendp) + { + const unsigned char *hdrstart = readp; + size_t start_offset = hdrstart - (const unsigned char *) data->d_buf; + + printf (gettext ("\nTable at offset %Zu:\n"), start_offset); + if (readp + 4 > readendp) + { + invalid_data: + error (0, 0, gettext ("invalid data in section [%zu] '%s'"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); + return; + } + + Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp); + unsigned int length_bytes = 4; + if (length == DWARF3_LENGTH_64_BIT) + { + if (readp + 8 > readendp) + goto invalid_data; + length = read_8ubyte_unaligned_inc (dbg, readp); + length_bytes = 8; + } + + const unsigned char *nexthdr = readp + length; + printf (gettext ("\n Length: %6" PRIu64 "\n"), + (uint64_t) length); + + if (unlikely (length > (size_t) (readendp - readp))) + goto invalid_data; + + if (length == 0) + continue; + + if (readp + 2 > readendp) + goto invalid_data; + uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp); + printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"), + version); + if (version != 2) + { + error (0, 0, gettext ("unsupported aranges version")); + goto next_table; + } + + Dwarf_Word offset; + if (readp + length_bytes > readendp) + goto invalid_data; + if (length_bytes == 8) + offset = read_8ubyte_unaligned_inc (dbg, readp); + else + offset = read_4ubyte_unaligned_inc (dbg, readp); + printf (gettext (" CU offset: %6" PRIx64 "\n"), + (uint64_t) offset); + + if (readp + 1 > readendp) + goto invalid_data; + unsigned int address_size = *readp++; + printf (gettext (" Address size: %6" PRIu64 "\n"), + (uint64_t) address_size); + if (address_size != 4 && address_size != 8) + { + error (0, 0, gettext ("unsupported address size")); + goto next_table; + } + + unsigned int segment_size = *readp++; + printf (gettext (" Segment size: %6" PRIu64 "\n\n"), + (uint64_t) segment_size); + if (segment_size != 0 && segment_size != 4 && segment_size != 8) + { + error (0, 0, gettext ("unsupported segment size")); + goto next_table; + } + + /* Round the address to the next multiple of 2*address_size. */ + readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size))) + % (2 * address_size)); + + while (readp < nexthdr) + { + Dwarf_Word range_address; + Dwarf_Word range_length; + Dwarf_Word segment = 0; + if (readp + 2 * address_size + segment_size > readendp) + goto invalid_data; + if (address_size == 4) + { + range_address = read_4ubyte_unaligned_inc (dbg, readp); + range_length = read_4ubyte_unaligned_inc (dbg, readp); + } + else + { + range_address = read_8ubyte_unaligned_inc (dbg, readp); + range_length = read_8ubyte_unaligned_inc (dbg, readp); + } + + if (segment_size == 4) + segment = read_4ubyte_unaligned_inc (dbg, readp); + else if (segment_size == 8) + segment = read_8ubyte_unaligned_inc (dbg, readp); + + if (range_address == 0 && range_length == 0 && segment == 0) + break; + + char *b = format_dwarf_addr (dwflmod, address_size, range_address, + range_address); + char *e = format_dwarf_addr (dwflmod, address_size, + range_address + range_length - 1, + range_length); + if (segment_size != 0) + printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e, + (uint64_t) segment); + else + printf (gettext (" %s..%s\n"), b, e); + free (b); + free (e); + } + + next_table: + if (readp != nexthdr) + { + size_t padding = nexthdr - readp; + printf (gettext (" %Zu padding bytes\n"), padding); + readp = nexthdr; + } + } +} + + /* Print content of DWARF .debug_ranges section. */ static void print_debug_ranges_section (Dwfl_Module *dwflmod, @@ -4694,7 +4820,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { - Elf_Data *data = elf_rawdata (scn, NULL); + Elf_Data *data = dbg->sectiondata[IDX_debug_ranges]; if (unlikely (data == NULL)) { @@ -4714,6 +4840,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; bool first = true; + Dwarf_Addr base = 0; unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size; unsigned char *readp = data->d_buf; while (readp < endp) @@ -4721,11 +4848,11 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, ptrdiff_t offset = readp - (unsigned char *) data->d_buf; if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx, - &address_size, NULL, + &address_size, NULL, &base, NULL, offset, &readp, endp)) continue; - if (unlikely (data->d_size - offset < address_size * 2)) + if (unlikely (data->d_size - offset < (size_t) address_size * 2)) { printf (gettext (" [%6tx] <INVALID DATA>\n"), offset); break; @@ -4748,9 +4875,10 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ { - char *b = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, end, end); printf (gettext (" [%6tx] base address %s\n"), offset, b); free (b); + base = end; } else if (begin == 0 && end == 0) /* End of list entry. */ { @@ -4760,8 +4888,10 @@ print_debug_ranges_section (Dwfl_Module *dwflmod, } else { - char *b = format_dwarf_addr (dwflmod, address_size, begin); - char *e = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, base + begin, + begin); + char *e = format_dwarf_addr (dwflmod, address_size, base + end, + end); /* We have an address range entry. */ if (first) /* First address range entry in a list. */ printf (gettext (" [%6tx] %s..%s\n"), offset, b, e); @@ -4787,9 +4917,12 @@ register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc, bits ?: &ignore, type ?: &ignore); if (n <= 0) { - snprintf (name, REGNAMESZ, "reg%u", loc->regno); + if (loc != NULL) + snprintf (name, REGNAMESZ, "reg%u", loc->regno); + else + snprintf (name, REGNAMESZ, "??? 0x%x", regno); if (bits != NULL) - *bits = loc->bits; + *bits = loc != NULL ? loc->bits : 0; if (type != NULL) *type = DW_ATE_unsigned; set = "??? unrecognized"; @@ -4797,7 +4930,7 @@ register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc, else { if (bits != NULL && *bits <= 0) - *bits = loc->bits; + *bits = loc != NULL ? loc->bits : 0; if (type != NULL && *type == DW_ATE_void) *type = DW_ATE_unsigned; @@ -4838,54 +4971,70 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, puts (" nop"); break; case DW_CFA_set_loc: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); op1 += vma_base; printf (" set_loc %" PRIu64 "\n", op1 * code_align); break; case DW_CFA_advance_loc1: + if ((uint64_t) (endp - readp) < 1) + goto invalid; printf (" advance_loc1 %u to %#" PRIx64 "\n", *readp, pc += *readp * code_align); ++readp; break; case DW_CFA_advance_loc2: + if ((uint64_t) (endp - readp) < 2) + goto invalid; op1 = read_2ubyte_unaligned_inc (dbg, readp); printf (" advance_loc2 %" PRIu64 " to %#" PRIx64 "\n", op1, pc += op1 * code_align); break; case DW_CFA_advance_loc4: + if ((uint64_t) (endp - readp) < 4) + goto invalid; op1 = read_4ubyte_unaligned_inc (dbg, readp); printf (" advance_loc4 %" PRIu64 " to %#" PRIx64 "\n", op1, pc += op1 * code_align); break; case DW_CFA_offset_extended: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); printf (" offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64 "\n", op1, regname (op1), op2 * data_align); break; case DW_CFA_restore_extended: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" restore_extended r%" PRIu64 " (%s)\n", op1, regname (op1)); break; case DW_CFA_undefined: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" undefined r%" PRIu64 " (%s)\n", op1, regname (op1)); break; case DW_CFA_same_value: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" same_value r%" PRIu64 " (%s)\n", op1, regname (op1)); break; case DW_CFA_register: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); printf (" register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n", op1, regname (op1), op2, regname (op2)); break; @@ -4896,83 +5045,123 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, puts (" restore_state"); break; case DW_CFA_def_cfa: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); printf (" def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n", op1, regname (op1), op2); break; case DW_CFA_def_cfa_register: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" def_cfa_register r%" PRIu64 " (%s)\n", op1, regname (op1)); break; case DW_CFA_def_cfa_offset: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" def_cfa_offset %" PRIu64 "\n", op1); break; case DW_CFA_def_cfa_expression: - // XXX overflow check - get_uleb128 (op1, readp); /* Length of DW_FORM_block. */ + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); /* Length of DW_FORM_block. */ printf (" def_cfa_expression %" PRIu64 "\n", op1); - print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op1, readp); + if ((uint64_t) (endp - readp) < op1) + { + invalid: + fputs (gettext (" <INVALID DATA>\n"), stdout); + return; + } + print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL, + op1, readp); readp += op1; break; case DW_CFA_expression: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); /* Length of DW_FORM_block. */ + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */ printf (" expression r%" PRIu64 " (%s) \n", op1, regname (op1)); - print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp); + if ((uint64_t) (endp - readp) < op2) + goto invalid; + print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL, + op2, readp); readp += op2; break; case DW_CFA_offset_extended_sf: - // XXX overflow check - get_uleb128 (op1, readp); - get_sleb128 (sop2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_sleb128 (sop2, readp, endp); printf (" offset_extended_sf r%" PRIu64 " (%s) at cfa%+" PRId64 "\n", op1, regname (op1), sop2 * data_align); break; case DW_CFA_def_cfa_sf: - // XXX overflow check - get_uleb128 (op1, readp); - get_sleb128 (sop2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_sleb128 (sop2, readp, endp); printf (" def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n", op1, regname (op1), sop2 * data_align); break; case DW_CFA_def_cfa_offset_sf: - // XXX overflow check - get_sleb128 (sop1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_sleb128 (sop1, readp, endp); printf (" def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align); break; case DW_CFA_val_offset: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); printf (" val_offset %" PRIu64 " at offset %" PRIu64 "\n", op1, op2 * data_align); break; case DW_CFA_val_offset_sf: - // XXX overflow check - get_uleb128 (op1, readp); - get_sleb128 (sop2, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_sleb128 (sop2, readp, endp); printf (" val_offset_sf %" PRIu64 " at offset %" PRId64 "\n", op1, sop2 * data_align); break; case DW_CFA_val_expression: - // XXX overflow check - get_uleb128 (op1, readp); - get_uleb128 (op2, readp); /* Length of DW_FORM_block. */ + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op2, readp, endp); /* Length of DW_FORM_block. */ printf (" val_expression r%" PRIu64 " (%s)\n", op1, regname (op1)); - print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, op2, readp); + if ((uint64_t) (endp - readp) < op2) + goto invalid; + print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, + NULL, op2, readp); readp += op2; break; case DW_CFA_MIPS_advance_loc8: + if ((uint64_t) (endp - readp) < 8) + goto invalid; op1 = read_8ubyte_unaligned_inc (dbg, readp); printf (" MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n", op1, pc += op1 * code_align); @@ -4981,8 +5170,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, puts (" GNU_window_save"); break; case DW_CFA_GNU_args_size: - // XXX overflow check - get_uleb128 (op1, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (op1, readp, endp); printf (" args_size %" PRIu64 "\n", op1); break; default: @@ -4995,8 +5185,9 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, else if (opcode < DW_CFA_restore) { uint64_t offset; - // XXX overflow check - get_uleb128 (offset, readp); + if ((uint64_t) (endp - readp) < 1) + goto invalid; + get_uleb128 (offset, readp, endp); printf (" offset r%u (%s) at cfa%+" PRId64 "\n", opcode & 0x3f, regname (opcode & 0x3f), offset * data_align); } @@ -5012,15 +5203,17 @@ encoded_ptr_size (int encoding, unsigned int ptr_size) { switch (encoding & 7) { - case 2: - return 2; - case 3: + case DW_EH_PE_udata4: return 4; - case 4: + case DW_EH_PE_udata8: return 8; - default: + case 0: return ptr_size; } + + fprintf (stderr, "Unsupported pointer encoding: %#x, " + "assuming pointer size of %d.\n", encoding, ptr_size); + return ptr_size; } @@ -5133,12 +5326,10 @@ read_encoded (unsigned int encoding, const unsigned char *readp, switch (encoding & 0xf) { case DW_EH_PE_uleb128: - // XXX buffer overrun check - get_uleb128 (*res, readp); + get_uleb128 (*res, readp, endp); break; case DW_EH_PE_sleb128: - // XXX buffer overrun check - get_sleb128 (*res, readp); + get_sleb128 (*res, readp, endp); break; case DW_EH_PE_udata2: if (readp + 2 > endp) @@ -5189,7 +5380,18 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, (void) elf_getshdrstrndx (ebl->elf, &shstrndx); const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); - Elf_Data *data = elf_rawdata (scn, NULL); + /* Needed if we find PC-relative addresses. */ + GElf_Addr bias; + if (dwfl_module_getelf (dwflmod, &bias) == NULL) + { + error (0, 0, gettext ("cannot get ELF: %s"), dwfl_errmsg (-1)); + return; + } + + bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0; + Elf_Data *data = (is_eh_frame + ? elf_rawdata (scn, NULL) + : dbg->sectiondata[IDX_debug_frame]); if (unlikely (data == NULL)) { @@ -5197,7 +5399,6 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, scnname, elf_errmsg (-1)); return; } - bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0; if (is_eh_frame) printf (gettext ("\ @@ -5254,6 +5455,10 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, continue; } + Dwarf_Word maxsize = dataend - readp; + if (unlikely (unit_length > maxsize)) + goto invalid_data; + unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; ptrdiff_t start = readp - (unsigned char *) data->d_buf; @@ -5297,21 +5502,24 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, segment_size = *readp++; } - // XXX Check overflow - get_uleb128 (code_alignment_factor, readp); - // XXX Check overflow - get_sleb128 (data_alignment_factor, readp); + if (cieend - readp < 1) + goto invalid_data; + get_uleb128 (code_alignment_factor, readp, cieend); + if (cieend - readp < 1) + goto invalid_data; + get_sleb128 (data_alignment_factor, readp, cieend); /* In some variant for unwind data there is another field. */ if (strcmp (augmentation, "eh") == 0) readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; unsigned int return_address_register; + if (cieend - readp < 1) + goto invalid_data; if (unlikely (version == 1)) return_address_register = *readp++; else - // XXX Check overflow - get_uleb128 (return_address_register, readp); + get_uleb128 (return_address_register, readp, cieend); printf ("\n [%6tx] CIE length=%" PRIu64 "\n" " CIE_id: %" PRIu64 "\n" @@ -5332,14 +5540,18 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (augmentation[0] == 'z') { unsigned int augmentationlen; - get_uleb128 (augmentationlen, readp); + get_uleb128 (augmentationlen, readp, cieend); - if (augmentationlen > (size_t) (dataend - readp)) - error (1, 0, gettext ("invalid augmentation length")); + if (augmentationlen > (size_t) (cieend - readp)) + { + error (0, 0, gettext ("invalid augmentation length")); + readp = cieend; + continue; + } const char *hdr = "Augmentation data:"; const char *cp = augmentation + 1; - while (*cp != '\0') + while (*cp != '\0' && cp < augmentation + augmentationlen + 1) { printf (" %-26s%#x ", hdr, *readp); hdr = ""; @@ -5431,12 +5643,25 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, const unsigned char *base = readp; // XXX There are sometimes relocations for this value - initial_location = read_ubyte_unaligned_inc (ptr_size, dbg, readp); + initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp); Dwarf_Word address_range - = read_ubyte_unaligned_inc (ptr_size, dbg, readp); + = read_addr_unaligned_inc (ptr_size, dbg, readp); + + /* pcrel for an FDE address is relative to the runtime + address of the start_address field itself. Sign extend + if necessary to make sure the calculation is done on the + full 64 bit address even when initial_location only holds + the lower 32 bits. */ + Dwarf_Addr pc_start = initial_location; + if (ptr_size == 4) + pc_start = (uint64_t) (int32_t) pc_start; + if ((fde_encoding & 0x70) == DW_EH_PE_pcrel) + pc_start += ((uint64_t) shdr->sh_addr + + (base - (const unsigned char *) data->d_buf) + - bias); char *a = format_dwarf_addr (dwflmod, cie->address_size, - initial_location); + pc_start, initial_location); printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n" " CIE_pointer: %" PRIu64 "\n" " initial_location: %s", @@ -5468,14 +5693,24 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (cie->augmentation[0] == 'z') { unsigned int augmentationlen; - get_uleb128 (augmentationlen, readp); + if (cieend - readp < 1) + goto invalid_data; + get_uleb128 (augmentationlen, readp, cieend); + + if (augmentationlen > (size_t) (cieend - readp)) + { + error (0, 0, gettext ("invalid augmentation length")); + readp = cieend; + continue; + } if (augmentationlen > 0) { const char *hdr = "Augmentation data:"; const char *cp = cie->augmentation + 1; unsigned int u = 0; - while (*cp != '\0') + while (*cp != '\0' + && cp < cie->augmentation + augmentationlen + 1) { if (*cp == 'L') { @@ -5505,9 +5740,12 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, } /* Handle the initialization instructions. */ - print_cfa_program (readp, cieend, vma_base, code_alignment_factor, - data_alignment_factor, version, ptr_size, - dwflmod, ebl, dbg); + if (ptr_size != 4 && ptr_size !=8) + printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size); + else + print_cfa_program (readp, cieend, vma_base, code_alignment_factor, + data_alignment_factor, version, ptr_size, + dwflmod, ebl, dbg); readp = cieend; } } @@ -5517,12 +5755,13 @@ struct attrcb_args { Dwfl_Module *dwflmod; Dwarf *dbg; + Dwarf_Die *die; int level; bool silent; unsigned int version; unsigned int addrsize; unsigned int offset_size; - Dwarf_Off cu_offset; + struct Dwarf_CU *cu; }; @@ -5564,10 +5803,11 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) dwarf_errmsg (-1)); return DWARF_CB_ABORT; } - char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr); + char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, + addr, addr); printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), a); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), a); free (a); } break; @@ -5575,14 +5815,15 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_indirect: case DW_FORM_strp: case DW_FORM_string: + case DW_FORM_GNU_strp_alt: if (cbargs->silent) break; const char *str = dwarf_formstring (attrp); if (unlikely (str == NULL)) goto attrval_out; printf (" %*s%-20s (%s) \"%s\"\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), str); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), str); break; case DW_FORM_ref_addr: @@ -5590,7 +5831,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_ref8: case DW_FORM_ref4: case DW_FORM_ref2: - case DW_FORM_ref1:; + case DW_FORM_ref1: + case DW_FORM_GNU_ref_alt: if (cbargs->silent) break; Dwarf_Die ref; @@ -5598,17 +5840,17 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref)); break; case DW_FORM_ref_sig8: if (cbargs->silent) break; printf (" %*s%-20s (%s) {%6" PRIx64 "}\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), - read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), + (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp)); break; case DW_FORM_sec_offset: @@ -5633,8 +5875,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) { if (!cbargs->silent) printf (" %*s%-20s (%s) %" PRIxMAX "\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num); return DWARF_CB_OK; } /* else fallthrough */ @@ -5652,52 +5894,60 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_AT_GNU_call_site_data_value: case DW_AT_GNU_call_site_target: case DW_AT_GNU_call_site_target_clobbered: - notice_listptr (section_loc, &known_loclistptr, - cbargs->addrsize, cbargs->offset_size, num); - if (!cbargs->silent) - printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + { + bool nlpt = notice_listptr (section_loc, &known_loclistptr, + cbargs->addrsize, cbargs->offset_size, + cbargs->cu, num); + if (!cbargs->silent) + printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num, + nlpt ? "" : " <WARNING offset too big>"); + } return DWARF_CB_OK; case DW_AT_ranges: - notice_listptr (section_ranges, &known_rangelistptr, - cbargs->addrsize, cbargs->offset_size, num); - if (!cbargs->silent) - printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + { + bool nlpt = notice_listptr (section_ranges, &known_rangelistptr, + cbargs->addrsize, cbargs->offset_size, + cbargs->cu, num); + if (!cbargs->silent) + printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num, + nlpt ? "" : " <WARNING offset too big>"); + } return DWARF_CB_OK; case DW_AT_language: - valuestr = dwarf_lang_string (num); + valuestr = dwarf_lang_name (num); break; case DW_AT_encoding: - valuestr = dwarf_encoding_string (num); + valuestr = dwarf_encoding_name (num); break; case DW_AT_accessibility: - valuestr = dwarf_access_string (num); + valuestr = dwarf_access_name (num); break; case DW_AT_visibility: - valuestr = dwarf_visibility_string (num); + valuestr = dwarf_visibility_name (num); break; case DW_AT_virtuality: - valuestr = dwarf_virtuality_string (num); + valuestr = dwarf_virtuality_name (num); break; case DW_AT_identifier_case: - valuestr = dwarf_identifier_case_string (num); + valuestr = dwarf_identifier_case_name (num); break; case DW_AT_calling_convention: - valuestr = dwarf_calling_convention_string (num); + valuestr = dwarf_calling_convention_name (num); break; case DW_AT_inline: - valuestr = dwarf_inline_string (num); + valuestr = dwarf_inline_name (num); break; case DW_AT_ordering: - valuestr = dwarf_ordering_string (num); + valuestr = dwarf_ordering_name (num); break; case DW_AT_discr_list: - valuestr = dwarf_discr_list_string (num); + valuestr = dwarf_discr_list_name (num); break; default: /* Nothing. */ @@ -5707,14 +5957,46 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break; - if (valuestr == NULL) - printf (" %*s%-20s (%s) %" PRIuMAX "\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + /* When highpc is in constant form it is relative to lowpc. + In that case also show the address. */ + Dwarf_Addr highpc; + if (attr == DW_AT_high_pc && dwarf_highpc (cbargs->die, &highpc) == 0) + { + char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, + highpc, highpc); + printf (" %*s%-20s (%s) %" PRIuMAX " (%s)\n", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num, a); + free (a); + } else - printf (" %*s%-20s (%s) %s (%" PRIuMAX ")\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), valuestr, (uintmax_t) num); + { + Dwarf_Sword snum = 0; + if (form == DW_FORM_sdata) + if (unlikely (dwarf_formsdata (attrp, &snum) != 0)) + goto attrval_out; + + if (valuestr == NULL) + { + printf (" %*s%-20s (%s)", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form)); + if (form == DW_FORM_sdata) + printf (" %" PRIdMAX "\n", (intmax_t) snum); + else + printf (" %" PRIuMAX "\n", (uintmax_t) num); + } + else + { + printf (" %*s%-20s (%s) %s", + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), valuestr); + if (form == DW_FORM_sdata) + printf (" (%" PRIdMAX ")\n", (intmax_t) snum); + else + printf (" (%" PRIuMAX ")\n", (uintmax_t) num); + } + } break; case DW_FORM_flag: @@ -5725,16 +6007,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR)); break; case DW_FORM_flag_present: if (cbargs->silent) break; printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), nl_langinfo (YESSTR)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), nl_langinfo (YESSTR)); break; case DW_FORM_exprloc: @@ -5749,8 +6031,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) ", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form)); switch (attr) { @@ -5789,7 +6071,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) print_ops (cbargs->dwflmod, cbargs->dbg, 12 + level * 2, 12 + level * 2, cbargs->version, cbargs->addrsize, cbargs->offset_size, - block.length, block.data); + attrp->cu, block.length, block.data); break; } break; @@ -5798,7 +6080,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break; printf (" %*s%-20s (form: %#x) ???\n", - (int) (level * 2), "", dwarf_attr_string (attr), + (int) (level * 2), "", dwarf_attr_name (attr), (int) form); break; } @@ -5871,8 +6153,7 @@ print_debug_units (Dwfl_Module *dwflmod, .silent = silent, .version = version, .addrsize = addrsize, - .offset_size = offsize, - .cu_offset = offset + .offset_size = offsize }; offset += cuhl; @@ -5889,6 +6170,8 @@ print_debug_units (Dwfl_Module *dwflmod, goto do_return; } + args.cu = dies[0].cu; + do { offset = dwarf_dieoffset (&dies[level]); @@ -5913,10 +6196,11 @@ print_debug_units (Dwfl_Module *dwflmod, if (!silent) printf (" [%6" PRIx64 "] %*s%s\n", (uint64_t) offset, (int) (level * 2), "", - dwarf_tag_string (tag)); + dwarf_tag_name (tag)); /* Print the attribute values. */ args.level = level; + args.die = &dies[level]; (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0); /* Make room for the next level's DIE. */ @@ -5976,9 +6260,105 @@ print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, static void +print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) +{ + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + + size_t address_size + = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; + + Dwarf_Off cuoffset; + Dwarf_Off ncuoffset = 0; + size_t hsize; + while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize, + NULL, NULL, NULL) == 0) + { + Dwarf_Die cudie; + if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL) + continue; + + size_t nlines; + Dwarf_Lines *lines; + if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0) + continue; + + printf (" CU [%" PRIx64 "] %s\n", + dwarf_dieoffset (&cudie), dwarf_diename (&cudie)); + printf (" line:col SBPE* disc isa op address" + " (Statement Block Prologue Epilogue *End)\n"); + const char *last_file = ""; + for (size_t n = 0; n < nlines; n++) + { + Dwarf_Line *line = dwarf_onesrcline (lines, n); + if (line == NULL) + { + printf (" dwarf_onesrcline: %s\n", dwarf_errmsg (-1)); + continue; + } + Dwarf_Word mtime, length; + const char *file = dwarf_linesrc (line, &mtime, &length); + if (file == NULL) + { + printf (" <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1)); + last_file = ""; + } + else if (strcmp (last_file, file) != 0) + { + printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n", + file, mtime, length); + last_file = file; + } + + int lineno, colno; + bool statement, endseq, block, prologue_end, epilogue_begin; + unsigned int lineop, isa, disc; + Dwarf_Addr address; + dwarf_lineaddr (line, &address); + dwarf_lineno (line, &lineno); + dwarf_linecol (line, &colno); + dwarf_lineop_index (line, &lineop); + dwarf_linebeginstatement (line, &statement); + dwarf_lineendsequence (line, &endseq); + dwarf_lineblock (line, &block); + dwarf_lineprologueend (line, &prologue_end); + dwarf_lineepiloguebegin (line, &epilogue_begin); + dwarf_lineisa (line, &isa); + dwarf_linediscriminator (line, &disc); + + /* End sequence is special, it is one byte past. */ + char *a = format_dwarf_addr (dwflmod, address_size, + address - (endseq ? 1 : 0), address); + printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n", + lineno, colno, + (statement ? 'S' : ' '), + (block ? 'B' : ' '), + (prologue_end ? 'P' : ' '), + (epilogue_begin ? 'E' : ' '), + (endseq ? '*' : ' '), + disc, isa, lineop, a); + free (a); + + if (endseq) + printf("\n"); + } + } +} + + +static void print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { + if (decodedline) + { + print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg); + return; + } + printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), elf_ndxscn (scn), section_name (ebl, ehdr, shdr), @@ -5989,7 +6369,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, /* There is no functionality in libdw to read the information in the way it is represented here. Hardcode the decoder. */ - Elf_Data *data = elf_getdata (scn, NULL); + Elf_Data *data = dbg->sectiondata[IDX_debug_line]; if (unlikely (data == NULL || data->d_buf == NULL)) { error (0, 0, gettext ("cannot get line data section data: %s"), @@ -6007,6 +6387,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, printf (gettext ("\nTable at offset %Zu:\n"), start_offset); + if (unlikely (linep + 4 > lineendp)) + goto invalid_data; Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); unsigned int length = 4; if (unlikely (unit_length == 0xffffffff)) @@ -6023,8 +6405,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, } /* Check whether we have enough room in the section. */ - if (unit_length < 2 + length + 5 * 1 - || unlikely (linep + unit_length > lineendp)) + if (unlikely (unit_length > (size_t) (lineendp - linep) + || unit_length < 2 + length + 5 * 1)) goto invalid_data; lineendp = linep + unit_length; @@ -6133,15 +6515,21 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, /* Then the index. */ unsigned int diridx; - get_uleb128 (diridx, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (diridx, linep, lineendp); /* Next comes the modification time. */ unsigned int mtime; - get_uleb128 (mtime, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (mtime, linep, lineendp); /* Finally the length of the file. */ unsigned int fsize; - get_uleb128 (fsize, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (fsize, linep, lineendp); printf (" %-5u %-5u %-9u %-9u %s\n", cnt, diridx, mtime, fsize, fname); @@ -6197,6 +6585,14 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, op_index = (op_index + op_advance) % max_ops_per_instr; } + if (max_ops_per_instr == 0) + { + error (0, 0, + gettext ("invalid maximum operations per instruction is zero")); + linep = lineendp; + continue; + } + while (linep < lineendp) { size_t offset = linep - (const unsigned char *) data->d_buf; @@ -6210,6 +6606,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, /* Is this a special opcode? */ if (likely (opcode >= opcode_base)) { + if (unlikely (line_range == 0)) + goto invalid_unit; + /* Yes. Handling this is quite easy since the opcode value is computed with @@ -6223,7 +6622,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, line += line_increment; advance_pc ((opcode - opcode_base) / line_range); - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, address); if (show_op_index) printf (gettext ("\ special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"), @@ -6266,12 +6665,14 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, case DW_LNE_set_address: op_index = 0; + if (unlikely ((size_t) (lineendp - linep) < address_size)) + goto invalid_unit; if (address_size == 4) address = read_4ubyte_unaligned_inc (dbg, linep); else address = read_8ubyte_unaligned_inc (dbg, linep); { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, address); printf (gettext (" set address to %s\n"), a); free (a); } @@ -6287,11 +6688,17 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, linep = endp + 1; unsigned int diridx; - get_uleb128 (diridx, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (diridx, linep, lineendp); Dwarf_Word mtime; - get_uleb128 (mtime, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (mtime, linep, lineendp); Dwarf_Word filelength; - get_uleb128 (filelength, linep); + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (filelength, linep, lineendp); printf (gettext ("\ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"), @@ -6305,7 +6712,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (unlikely (standard_opcode_lengths[opcode] != 1)) goto invalid_unit; - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); printf (gettext (" set discriminator to %u\n"), u128); break; @@ -6329,10 +6736,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, case DW_LNS_advance_pc: /* Takes one uleb128 parameter which is added to the address. */ - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); advance_pc (u128); { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, address); if (show_op_index) printf (gettext ("\ advance address by %u to %s, op_index to %u\n"), @@ -6347,7 +6754,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, case DW_LNS_advance_line: /* Takes one sleb128 parameter which is added to the line. */ - get_sleb128 (s128, linep); + get_sleb128 (s128, linep, lineendp); line += s128; printf (gettext ("\ advance line by constant %d to %" PRId64 "\n"), @@ -6356,7 +6763,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, case DW_LNS_set_file: /* Takes one uleb128 parameter which is stored in file. */ - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); printf (gettext (" set file to %" PRIu64 "\n"), (uint64_t) u128); break; @@ -6366,7 +6773,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (unlikely (standard_opcode_lengths[opcode] != 1)) goto invalid_unit; - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); printf (gettext (" set column to %" PRIu64 "\n"), (uint64_t) u128); break; @@ -6385,9 +6792,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, case DW_LNS_const_add_pc: /* Takes no argument. */ + + if (unlikely (line_range == 0)) + goto invalid_unit; + advance_pc ((255 - opcode_base) / line_range); { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, address); if (show_op_index) printf (gettext ("\ advance address by constant %u to %s, op_index to %u\n"), @@ -6410,7 +6821,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, address += u128; op_index = 0; { - char *a = format_dwarf_addr (dwflmod, 0, address); + char *a = format_dwarf_addr (dwflmod, 0, address, address); printf (gettext ("\ advance address by fixed value %u to %s\n"), u128, a); @@ -6433,7 +6844,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (unlikely (standard_opcode_lengths[opcode] != 1)) goto invalid_unit; - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); printf (gettext (" set isa to %u\n"), u128); break; } @@ -6449,7 +6860,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, standard_opcode_lengths[opcode]); for (int n = standard_opcode_lengths[opcode]; n > 0; --n) { - get_uleb128 (u128, linep); + get_uleb128 (u128, linep, lineendp); if (n != standard_opcode_lengths[opcode]) putc_unlocked (',', stdout); printf (" %u", u128); @@ -6471,7 +6882,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { - Elf_Data *data = elf_rawdata (scn, NULL); + Elf_Data *data = dbg->sectiondata[IDX_debug_loc]; if (unlikely (data == NULL)) { @@ -6492,6 +6903,8 @@ print_debug_loc_section (Dwfl_Module *dwflmod, uint_fast8_t offset_size = 4; bool first = true; + struct Dwarf_CU *cu = NULL; + Dwarf_Addr base = 0; unsigned char *readp = data->d_buf; unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size; while (readp < endp) @@ -6499,11 +6912,11 @@ print_debug_loc_section (Dwfl_Module *dwflmod, ptrdiff_t offset = readp - (unsigned char *) data->d_buf; if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx, - &address_size, &offset_size, - offset, &readp, endp)) + &address_size, &offset_size, &base, + &cu, offset, &readp, endp)) continue; - if (unlikely (data->d_size - offset < address_size * 2)) + if (unlikely (data->d_size - offset < (size_t) address_size * 2)) { printf (gettext (" [%6tx] <INVALID DATA>\n"), offset); break; @@ -6526,9 +6939,10 @@ print_debug_loc_section (Dwfl_Module *dwflmod, if (begin == (Dwarf_Addr) -1l) /* Base address entry. */ { - char *b = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, end, end); printf (gettext (" [%6tx] base address %s\n"), offset, b); free (b); + base = end; } else if (begin == 0 && end == 0) /* End of list entry. */ { @@ -6541,8 +6955,10 @@ print_debug_loc_section (Dwfl_Module *dwflmod, /* We have a location expression entry. */ uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp); - char *b = format_dwarf_addr (dwflmod, address_size, begin); - char *e = format_dwarf_addr (dwflmod, address_size, end); + char *b = format_dwarf_addr (dwflmod, address_size, base + begin, + begin); + char *e = format_dwarf_addr (dwflmod, address_size, base + end, + end); if (first) /* First entry in a list. */ printf (gettext (" [%6tx] %s..%s"), offset, b, e); @@ -6559,7 +6975,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod, } print_ops (dwflmod, dbg, 1, 18 + (address_size * 4), - 3 /*XXX*/, address_size, offset_size, len, readp); + 3 /*XXX*/, address_size, offset_size, cu, len, readp); first = false; readp += len; @@ -6603,7 +7019,7 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), /* There is no function in libdw to iterate over the raw content of the section but it is easy enough to do. */ - Elf_Data *data = elf_getdata (scn, NULL); + Elf_Data *data = dbg->sectiondata[IDX_debug_macinfo]; if (unlikely (data == NULL || data->d_buf == NULL)) { error (0, 0, gettext ("cannot get macro information section data: %s"), @@ -6680,7 +7096,7 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), For the latter number, string. We can treat these cases together. */ - get_uleb128 (u128, readp); + get_uleb128 (u128, readp, readendp); endp = memchr (readp, '\0', readendp - readp); if (unlikely (endp == NULL)) @@ -6705,8 +7121,15 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), case DW_MACINFO_start_file: /* The two parameters are line and file index, in this order. */ - get_uleb128 (u128, readp); - get_uleb128 (u128_2, readp); + get_uleb128 (u128, readp, readendp); + if (readendp - readp < 1) + { + printf (gettext ("\ +%*s*** missing DW_MACINFO_start_file argument at end of section"), + level, ""); + return; + } + get_uleb128 (u128_2, readp, readendp); /* Find the CU DIE for this file. */ size_t macoff = readp - (const unsigned char *) data->d_buf; @@ -6746,6 +7169,415 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } +static void +print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) +{ + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + putc_unlocked ('\n', stdout); + + Elf_Data *data = dbg->sectiondata[IDX_debug_macro]; + if (unlikely (data == NULL || data->d_buf == NULL)) + { + error (0, 0, gettext ("cannot get macro information section data: %s"), + elf_errmsg (-1)); + return; + } + + /* Get the source file information for all CUs. Uses same + datastructure as macinfo. But uses offset field to directly + match .debug_line offset. And just stored in a list. */ + Dwarf_Off offset; + Dwarf_Off ncu = 0; + size_t hsize; + struct mac_culist *culist = NULL; + size_t nculist = 0; + while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0) + { + Dwarf_Die cudie; + if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL) + continue; + + Dwarf_Attribute attr; + if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL) + continue; + + Dwarf_Word lineoff; + if (dwarf_formudata (&attr, &lineoff) != 0) + continue; + + struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp)); + newp->die = cudie; + newp->offset = lineoff; + newp->files = NULL; + newp->next = culist; + culist = newp; + ++nculist; + } + + const unsigned char *readp = (const unsigned char *) data->d_buf; + const unsigned char *readendp = readp + data->d_size; + + while (readp < readendp) + { + printf (gettext (" Offset: 0x%" PRIx64 "\n"), + (uint64_t) (readp - (const unsigned char *) data->d_buf)); + + // Header, 2 byte version, 1 byte flag, optional .debug_line offset, + // optional vendor extension macro entry table. + if (readp + 2 > readendp) + { + invalid_data: + error (0, 0, gettext ("invalid data")); + return; + } + const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp); + printf (gettext (" Version: %" PRIu16 "\n"), vers); + + // Version 4 is the GNU extension for DWARF4. DWARF5 will use version + // 5 when it gets standardized. + if (vers != 4) + { + printf (gettext (" unknown version, cannot parse section\n")); + return; + } + + if (readp + 1 > readendp) + goto invalid_data; + const unsigned char flag = *readp++; + printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag); + + unsigned int offset_len = (flag & 0x01) ? 8 : 4; + printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len); + Dwarf_Off line_offset = -1; + if (flag & 0x02) + { + if (offset_len == 8) + line_offset = read_8ubyte_unaligned_inc (dbg, readp); + else + line_offset = read_4ubyte_unaligned_inc (dbg, readp); + printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"), + line_offset); + } + + const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user]; + memset (vendor, 0, sizeof vendor); + if (flag & 0x04) + { + // 1 byte length, for each item, 1 byte opcode, uleb128 number + // of arguments, for each argument 1 byte form code. + if (readp + 1 > readendp) + goto invalid_data; + unsigned int tlen = *readp++; + printf (gettext (" extension opcode table, %" PRIu8 " items:\n"), + tlen); + for (unsigned int i = 0; i < tlen; i++) + { + if (readp + 1 > readendp) + goto invalid_data; + unsigned int opcode = *readp++; + printf (gettext (" [%" PRIx8 "]"), opcode); + if (opcode < DW_MACRO_GNU_lo_user + || opcode > DW_MACRO_GNU_hi_user) + goto invalid_data; + // Record the start of description for this vendor opcode. + // uleb128 nr args, 1 byte per arg form. + vendor[opcode - DW_MACRO_GNU_lo_user] = readp; + if (readp + 1 > readendp) + goto invalid_data; + unsigned int args = *readp++; + if (args > 0) + { + printf (gettext (" %" PRIu8 " arguments:"), args); + while (args > 0) + { + if (readp + 1 > readendp) + goto invalid_data; + unsigned int form = *readp++; + printf (" %s", dwarf_form_string (form)); + if (form != DW_FORM_data1 + && form != DW_FORM_data2 + && form != DW_FORM_data4 + && form != DW_FORM_data8 + && form != DW_FORM_sdata + && form != DW_FORM_udata + && form != DW_FORM_block + && form != DW_FORM_block1 + && form != DW_FORM_block2 + && form != DW_FORM_block4 + && form != DW_FORM_flag + && form != DW_FORM_string + && form != DW_FORM_strp + && form != DW_FORM_sec_offset) + goto invalid_data; + args--; + if (args > 0) + putchar_unlocked (','); + } + } + else + printf (gettext (" no arguments.")); + putchar_unlocked ('\n'); + } + } + putchar_unlocked ('\n'); + + int level = 1; + if (readp + 1 > readendp) + goto invalid_data; + unsigned int opcode = *readp++; + while (opcode != 0) + { + unsigned int u128; + unsigned int u128_2; + const unsigned char *endp; + uint64_t off; + + switch (opcode) + { + case DW_MACRO_GNU_start_file: + get_uleb128 (u128, readp, readendp); + if (readp >= readendp) + goto invalid_data; + get_uleb128 (u128_2, readp, readendp); + + /* Find the CU DIE that matches this line offset. */ + const char *fname = "???"; + if (line_offset != (Dwarf_Off) -1) + { + struct mac_culist *cu = culist; + while (cu != NULL && line_offset != cu->offset) + cu = cu->next; + if (cu != NULL) + { + if (cu->files == NULL + && dwarf_getsrcfiles (&cu->die, &cu->files, + NULL) != 0) + cu->files = (Dwarf_Files *) -1l; + + if (cu->files != (Dwarf_Files *) -1l) + fname = (dwarf_filesrc (cu->files, u128_2, + NULL, NULL) ?: "???"); + } + } + printf ("%*sstart_file %u, [%u] %s\n", + level, "", u128, u128_2, fname); + ++level; + break; + + case DW_MACRO_GNU_end_file: + --level; + printf ("%*send_file\n", level, ""); + break; + + case DW_MACRO_GNU_define: + get_uleb128 (u128, readp, readendp); + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf ("%*s#define %s, line %u\n", + level, "", readp, u128); + readp = endp + 1; + break; + + case DW_MACRO_GNU_undef: + get_uleb128 (u128, readp, readendp); + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf ("%*s#undef %s, line %u\n", + level, "", readp, u128); + readp = endp + 1; + break; + + case DW_MACRO_GNU_define_indirect: + get_uleb128 (u128, readp, readendp); + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + off = read_8ubyte_unaligned_inc (dbg, readp); + else + off = read_4ubyte_unaligned_inc (dbg, readp); + printf ("%*s#define %s, line %u (indirect)\n", + level, "", dwarf_getstring (dbg, off, NULL), u128); + break; + + case DW_MACRO_GNU_undef_indirect: + get_uleb128 (u128, readp, readendp); + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + off = read_8ubyte_unaligned_inc (dbg, readp); + else + off = read_4ubyte_unaligned_inc (dbg, readp); + printf ("%*s#undef %s, line %u (indirect)\n", + level, "", dwarf_getstring (dbg, off, NULL), u128); + break; + + case DW_MACRO_GNU_transparent_include: + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + off = read_8ubyte_unaligned_inc (dbg, readp); + else + off = read_4ubyte_unaligned_inc (dbg, readp); + printf ("%*s#include offset 0x%" PRIx64 "\n", + level, "", off); + break; + + default: + printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode); + if (opcode < DW_MACRO_GNU_lo_user + || opcode > DW_MACRO_GNU_lo_user + || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL) + goto invalid_data; + + const unsigned char *op_desc; + op_desc = vendor[opcode - DW_MACRO_GNU_lo_user]; + + // Just skip the arguments, we cannot really interpret them, + // but print as much as we can. + unsigned int args = *op_desc++; + while (args > 0) + { + unsigned int form = *op_desc++; + Dwarf_Word val; + switch (form) + { + case DW_FORM_data1: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" %" PRIx8, (unsigned int) val); + break; + + case DW_FORM_data2: + if (readp + 2 > readendp) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + printf(" %" PRIx16, (unsigned int) val); + break; + + case DW_FORM_data4: + if (readp + 4 > readendp) + goto invalid_data; + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx32, (unsigned int) val); + break; + + case DW_FORM_data8: + if (readp + 8 > readendp) + goto invalid_data; + val = read_8ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_sdata: + get_sleb128 (val, readp, readendp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_udata: + get_uleb128 (val, readp, readendp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_block: + get_uleb128 (val, readp, readendp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + readp += val; + break; + + case DW_FORM_block1: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_block2: + if (readp + 2 > readendp) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_block4: + if (readp + 2 > readendp) + goto invalid_data; + val =read_4ubyte_unaligned_inc (dbg, readp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_flag: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR)); + break; + + case DW_FORM_string: + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf (" %s", readp); + readp = endp + 1; + break; + + case DW_FORM_strp: + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %s", dwarf_getstring (dbg, val, NULL)); + break; + + case DW_FORM_sec_offset: + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx64, val); + break; + + default: + error (0, 0, gettext ("vendor opcode not verified?")); + return; + } + + args--; + if (args > 0) + putchar_unlocked (','); + } + putchar_unlocked ('\n'); + } + + if (readp + 1 > readendp) + goto invalid_data; + opcode = *readp++; + if (opcode == 0) + putchar_unlocked ('\n'); + } + } +} + + /* Callback for printing global names. */ static int print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global, @@ -6781,7 +7613,8 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { - const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size; + const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ? + dbg->sectiondata[IDX_debug_str]->d_size : 0); /* Compute floor(log16(shdr->sh_size)). */ GElf_Addr tmp = sh_size; @@ -6970,9 +7803,10 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), if (ttype_encoding != DW_EH_PE_omit) { unsigned int ttype_base_offset; - get_uleb128 (ttype_base_offset, readp); + get_uleb128 (ttype_base_offset, readp, dataend); printf (" TType base offset: %#x\n", ttype_base_offset); - ttype_base = readp + ttype_base_offset; + if ((size_t) (dataend - readp) > ttype_base_offset) + ttype_base = readp + ttype_base_offset; } if (unlikely (readp + 1 > dataend)) @@ -6981,7 +7815,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), printf (gettext (" Call site encoding: %#x "), call_site_encoding); print_encoding_base ("", call_site_encoding); unsigned int call_site_table_len; - get_uleb128 (call_site_table_len, readp); + get_uleb128 (call_site_table_len, readp, dataend); const unsigned char *const action_table = readp + call_site_table_len; if (unlikely (action_table > dataend)) @@ -7003,7 +7837,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), readp = read_encoded (call_site_encoding, readp, dataend, &landing_pad, dbg); unsigned int action; - get_uleb128 (action, readp); + get_uleb128 (action, readp, dataend); max_action = MAX (action, max_action); printf (gettext (" [%4u] Call site start: %#" PRIx64 "\n" " Call site length: %" PRIu64 "\n" @@ -7011,13 +7845,20 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), " Action: %u\n"), u++, call_site_start, call_site_length, landing_pad, action); } - assert (readp == action_table); + if (readp != action_table) + goto invalid_data; unsigned int max_ar_filter = 0; if (max_action > 0) { puts ("\n Action table:"); + if ((size_t) (dataend - action_table) < max_action + 1) + { + fputs (gettext (" <INVALID DATA>\n"), stdout); + return; + } + const unsigned char *const action_table_end = action_table + max_action + 1; @@ -7025,11 +7866,11 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), do { int ar_filter; - get_sleb128 (ar_filter, readp); + get_sleb128 (ar_filter, readp, action_table_end); if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter) max_ar_filter = ar_filter; int ar_disp; - get_sleb128 (ar_disp, readp); + get_sleb128 (ar_disp, readp, action_table_end); printf (" [%4u] ar_filter: % d\n" " ar_disp: % -5d", @@ -7045,7 +7886,7 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)), while (readp < action_table_end); } - if (max_ar_filter > 0) + if (max_ar_filter > 0 && ttype_base != NULL) { puts ("\n TType table:"); @@ -7118,8 +7959,11 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, printf (gettext (" Version: %" PRId32 "\n"), vers); // The only difference between version 4 and version 5 is the - // hash used for generating the table. - if (vers < 4 || vers > 5) + // hash used for generating the table. Version 6 contains symbols + // for inlined functions, older versions didn't. Version 7 adds + // symbol kinds. Version 8 just indicates that it correctly includes + // TUs for symbols. + if (vers < 4 || vers > 8) { printf (gettext (" unknown version, cannot parse section\n")); return; @@ -7163,14 +8007,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + cu_off; const unsigned char *nextp = data->d_buf + tu_off; - size_t nr = (nextp - readp) / 16; + size_t cu_nr = (nextp - readp) / 16; printf (gettext ("\n CU list at offset %#" PRIx32 " contains %zu entries:\n"), - cu_off, nr); + cu_off, cu_nr); size_t n = 0; - while (readp + 16 <= dataend && n < nr) + while (readp + 16 <= dataend && n < cu_nr) { uint64_t off = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7185,14 +8029,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + tu_off; nextp = data->d_buf + addr_off; - nr = (nextp - readp) / 24; + size_t tu_nr = (nextp - readp) / 24; printf (gettext ("\n TU list at offset %#" PRIx32 " contains %zu entries:\n"), - tu_off, nr); + tu_off, tu_nr); n = 0; - while (readp + 24 <= dataend && n < nr) + while (readp + 24 <= dataend && n < tu_nr) { uint64_t off = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7211,14 +8055,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + addr_off; nextp = data->d_buf + sym_off; - nr = (nextp - readp) / 20; + size_t addr_nr = (nextp - readp) / 20; printf (gettext ("\n Address list at offset %#" PRIx32 " contains %zu entries:\n"), - addr_off, nr); + addr_off, addr_nr); n = 0; - while (readp + 20 <= dataend && n < nr) + while (readp + 20 <= dataend && n < addr_nr) { uint64_t low = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7229,23 +8073,25 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, uint32_t idx = read_4ubyte_unaligned (dbg, readp); readp += 4; - char *l = format_dwarf_addr (dwflmod, 8, low); - char *h = format_dwarf_addr (dwflmod, 8, high - 1); + char *l = format_dwarf_addr (dwflmod, 8, low, low); + char *h = format_dwarf_addr (dwflmod, 8, high - 1, high); printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n", n, l, h, idx); + free (l); + free (h); n++; } readp = data->d_buf + sym_off; nextp = data->d_buf + const_off; - nr = (nextp - readp) / 8; + size_t sym_nr = (nextp - readp) / 8; printf (gettext ("\n Symbol table at offset %#" PRIx32 " contains %zu slots:\n"), - addr_off, nr); + addr_off, sym_nr); n = 0; - while (readp + 8 <= dataend && n < nr) + while (readp + 8 <= dataend && n < sym_nr) { uint32_t name = read_4ubyte_unaligned (dbg, readp); readp += 4; @@ -7256,22 +8102,56 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, if (name != 0 || vector != 0) { const unsigned char *sym = data->d_buf + const_off + name; - if (unlikely (sym > dataend)) + if (unlikely (sym > dataend + || memchr (sym, '\0', dataend - sym) == NULL)) goto invalid_data; printf (" [%4zu] symbol: %s, CUs: ", n, sym); const unsigned char *readcus = data->d_buf + const_off + vector; - if (unlikely (readcus + 8 > dataend)) + if (unlikely (readcus + 4 > dataend)) goto invalid_data; - uint32_t cus = read_4ubyte_unaligned (dbg, readcus); while (cus--) { - uint32_t cu; + uint32_t cu_kind, cu, kind; + bool is_static; readcus += 4; - cu = read_4ubyte_unaligned (dbg, readcus); - printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : "")); + if (unlikely (readcus + 4 > dataend)) + goto invalid_data; + cu_kind = read_4ubyte_unaligned (dbg, readcus); + cu = cu_kind & ((1 << 24) - 1); + kind = (cu_kind >> 28) & 7; + is_static = cu_kind & (1U << 31); + if (cu > cu_nr - 1) + printf ("%" PRId32 "T", cu - (uint32_t) cu_nr); + else + printf ("%" PRId32, cu); + if (kind != 0) + { + printf (" ("); + switch (kind) + { + case 1: + printf ("type"); + break; + case 2: + printf ("var"); + break; + case 3: + printf ("func"); + break; + case 4: + printf ("other"); + break; + default: + printf ("unknown-0x%" PRIx32, kind); + break; + } + printf (":%c)", (is_static ? 'S' : 'G')); + } + if (cus > 0) + printf (", "); } printf ("\n"); } @@ -7335,6 +8215,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) NEW_SECTION (pubnames), NEW_SECTION (str), NEW_SECTION (macinfo), + NEW_SECTION (macro), NEW_SECTION (ranges), { ".eh_frame", section_frame | section_exception, print_debug_frame_section }, @@ -7348,8 +8229,10 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) / sizeof (debug_sections[0])); const char *name = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); - int n; + if (name == NULL) + continue; + int n; for (n = 0; n < ndebug_sections; ++n) if (strcmp (name, debug_sections[n].name) == 0 #if USE_ZLIB @@ -7373,24 +8256,35 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) #define ITEM_INDENT 4 -#define ITEM_WRAP_COLUMN 150 -#define REGISTER_WRAP_COLUMN 75 +#define WRAP_COLUMN 75 + +/* Print "NAME: FORMAT", wrapping when output text would make the line + exceed WRAP_COLUMN. Unpadded numbers look better for the core items + but this function is also used for registers which should be printed + aligned. Fortunately registers output uses fixed fields width (such + as %11d) for the alignment. + + Line breaks should not depend on the particular values although that + may happen in some cases of the core items. */ -/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would - make the line exceed ITEM_WRAP_COLUMN. Unpadded numbers look better - for the core items. But we do not want the line breaks to depend on - the particular values. */ static unsigned int -__attribute__ ((format (printf, 7, 8))) +__attribute__ ((format (printf, 6, 7))) print_core_item (unsigned int colno, char sep, unsigned int wrap, - size_t name_width, const char *name, - size_t format_max, const char *format, ...) + size_t name_width, const char *name, const char *format, ...) { size_t len = strlen (name); if (name_width < len) name_width = len; - size_t n = name_width + sizeof ": " - 1 + format_max; + char *out; + va_list ap; + va_start (ap, format); + int out_len = vasprintf (&out, format, ap); + va_end (ap); + if (out_len == -1) + error (EXIT_FAILURE, 0, _("memory exhausted")); + + size_t n = name_width + sizeof ": " - 1 + out_len; if (colno == 0) { @@ -7408,12 +8302,9 @@ print_core_item (unsigned int colno, char sep, unsigned int wrap, colno = ITEM_INDENT + n; } - printf ("%s: %*s", name, (int) (name_width - len), ""); + printf ("%s: %*s%s", name, (int) (name_width - len), "", out); - va_list ap; - va_start (ap, format); - vprintf (format, ap); - va_end (ap); + free (out); return colno; } @@ -7456,14 +8347,14 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, uint_fast16_t count = item->count ?: 1; #define TYPES \ - DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4); \ - DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6); \ - DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11); \ - DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11); \ - DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20); \ - DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20) - -#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count] + DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8); \ + DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16); \ + DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32); \ + DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32); \ + DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64); \ + DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64) + +#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name[count] union { TYPES; } value; #undef DO_TYPE @@ -7495,10 +8386,10 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, assert (count == 1); switch (type) { -#define DO_TYPE(NAME, Name, hex, dec, max) \ +#define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \ - 0, item->name, max, dec, value.Name[0]); \ + colno = print_core_item (colno, ',', WRAP_COLUMN, \ + 0, item->name, dec, value.Name[0]); \ break TYPES; #undef DO_TYPE @@ -7511,10 +8402,10 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, assert (count == 1); switch (type) { -#define DO_TYPE(NAME, Name, hex, dec, max) \ +#define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \ - 0, item->name, max, hex, value.Name[0]); \ + colno = print_core_item (colno, ',', WRAP_COLUMN, \ + 0, item->name, hex, value.Name[0]); \ break TYPES; #undef DO_TYPE @@ -7534,7 +8425,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, const unsigned int bias = item->format == 'b'; { - char printed[(negate ? nbits - pop : pop) * 16]; + char printed[(negate ? nbits - pop : pop) * 16 + 1]; char *p = printed; *p = '\0'; @@ -7551,19 +8442,19 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, } unsigned int lastbit = 0; + unsigned int run = 0; for (const unsigned int *i = data; (void *) i < data + count * size; ++i) { unsigned int bit = ((void *) i - data) * 8; unsigned int w = negate ? ~*i : *i; - unsigned int run = 0; while (w != 0) { int n = ffs (w); w >>= n; bit += n; - if (lastbit + 1 == bit) + if (lastbit != 0 && lastbit + 1 == bit) ++run; else { @@ -7579,11 +8470,10 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, lastbit = bit; } } - if (lastbit > 0 && lastbit + 1 != nbits) - p += sprintf (p, "-%u", nbits - bias); + if (lastbit > 0 && run > 0 && lastbit + 1 != nbits) + p += sprintf (p, "-%u", lastbit - bias); - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, - 4 + nbits * 4, + colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, negate ? "~<%s>" : "<%s>", printed); } break; @@ -7593,14 +8483,12 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, assert (count == 2); Dwarf_Word sec; Dwarf_Word usec; - size_t maxfmt = 7; switch (type) { -#define DO_TYPE(NAME, Name, hex, dec, max) \ +#define DO_TYPE(NAME, Name, hex, dec) \ case ELF_T_##NAME: \ sec = value.Name[0]; \ usec = value.Name[1]; \ - maxfmt += max; \ break TYPES; #undef DO_TYPE @@ -7623,19 +8511,19 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, else usec &= UINT32_MAX; } - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, - maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec); + colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, + "%" PRIu64 ".%.6" PRIu64, sec, usec); break; case 'c': assert (count == 1); - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, - 1, "%c", value.Byte[0]); + colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, + "%c", value.Byte[0]); break; case 's': - colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name, - count, "%.*s", (int) count, value.Byte); + colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name, + "%.*s", (int) count, value.Byte); break; case '\n': @@ -7662,7 +8550,10 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, s = eol + 1; } - colno = ITEM_WRAP_COLUMN; + colno = WRAP_COLUMN; + break; + + case 'h': break; default: @@ -7711,6 +8602,24 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, { if (nitems == 0) return 0; + unsigned int colno = 0; + + /* FORMAT '\n' makes sense to be present only as a single item as it + processes all the data of a note. FORMATs 'b' and 'B' have a special case + if present as a single item but they can be also processed with other + items below. */ + if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b' + || items[0].format == 'B')) + { + assert (items[0].offset == 0); + size_t size = descsz; + colno = handle_core_item (core, items, desc, colno, &size); + /* If SIZE is not zero here there is some remaining data. But we do not + know how to process it anyway. */ + return colno; + } + for (size_t i = 0; i < nitems; ++i) + assert (items[i].format != '\n'); /* Sort to collect the groups together. */ const Ebl_Core_Item *sorted_items[nitems]; @@ -7729,19 +8638,7 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups); /* Write out all the groups. */ - unsigned int colno = 0; - const void *last = desc; - if (nitems == 1) - { - size_t size = descsz; - colno = handle_core_item (core, sorted_items[0], desc, colno, &size); - if (size == 0) - return colno; - desc += descsz - size; - descsz = size; - } - do { for (size_t i = 0; i < ngroups; ++i) @@ -7754,7 +8651,7 @@ handle_core_items (Elf *core, const void *desc, size_t descsz, colno = handle_core_item (core, *item, desc, colno, NULL); /* Force a line break at the end of the group. */ - colno = ITEM_WRAP_COLUMN; + colno = WRAP_COLUMN; } if (descsz == 0) @@ -7822,12 +8719,12 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, register_info (ebl, reg, regloc, name, &bits, &type); #define TYPES \ - BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \ - BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6); \ - BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11); \ - BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64, 20) + BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8); \ + BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16); \ + BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32); \ + BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64) -#define BITS(bits, xtype, sfmt, ufmt, max) \ +#define BITS(bits, xtype, sfmt, ufmt) \ uint##bits##_t b##bits; int##bits##_t b##bits##s union { TYPES; uint64_t b128[2]; } value; #undef BITS @@ -7839,17 +8736,17 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, case DW_ATE_address: switch (bits) { -#define BITS(bits, xtype, sfmt, ufmt, max) \ +#define BITS(bits, xtype, sfmt, ufmt) \ case bits: \ desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0); \ if (type == DW_ATE_signed) \ - colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \ + colno = print_core_item (colno, ' ', WRAP_COLUMN, \ maxregname, name, \ - max, sfmt, value.b##bits##s); \ + sfmt, value.b##bits##s); \ else \ - colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \ + colno = print_core_item (colno, ' ', WRAP_COLUMN, \ maxregname, name, \ - max, ufmt, value.b##bits); \ + ufmt, value.b##bits); \ break TYPES; @@ -7858,9 +8755,9 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, assert (type == DW_ATE_unsigned); desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0); int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB; - colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, + colno = print_core_item (colno, ' ', WRAP_COLUMN, maxregname, name, - 34, "0x%.16" PRIx64 "%.16" PRIx64, + "0x%.16" PRIx64 "%.16" PRIx64, value.b128[!be], value.b128[be]); break; @@ -7889,9 +8786,8 @@ handle_core_register (Ebl *ebl, Elf *core, int maxregname, *h++ = "0123456789abcdef"[bytes[idx] >> 4]; *h++ = "0123456789abcdef"[bytes[idx] & 0xf]; } - colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, - maxregname, name, - 2 + sizeof hex - 1, "0x%s", hex); + colno = print_core_item (colno, ' ', WRAP_COLUMN, + maxregname, name, "0x%s", hex); break; } desc += regloc->pad; @@ -8030,7 +8926,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc, reg->regloc, desc, colno); /* Force a line break at the end of the group. */ - colno = REGISTER_WRAP_COLUMN; + colno = WRAP_COLUMN; } return colno; @@ -8108,6 +9004,155 @@ handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos) } } +static bool +buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz) +{ + return ptr < end && (size_t) (end - ptr) >= sz; +} + +static bool +buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end, + int *retp) +{ + if (! buf_has_data (*ptrp, end, 4)) + return false; + + *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4); + return true; +} + +static bool +buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end, + uint64_t *retp) +{ + size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT); + if (! buf_has_data (*ptrp, end, sz)) + return false; + + union + { + uint64_t u64; + uint32_t u32; + } u; + + *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz); + + if (sz == 4) + *retp = u.u32; + else + *retp = u.u64; + return true; +} + +static void +handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos) +{ + Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE); + if (data == NULL) + error (EXIT_FAILURE, 0, + gettext ("cannot convert core note data: %s"), elf_errmsg (-1)); + + unsigned char const *ptr = data->d_buf; + unsigned char const *const end = data->d_buf + data->d_size; + + /* Siginfo head is three ints: signal number, error number, origin + code. */ + int si_signo, si_errno, si_code; + if (! buf_read_int (core, &ptr, end, &si_signo) + || ! buf_read_int (core, &ptr, end, &si_errno) + || ! buf_read_int (core, &ptr, end, &si_code)) + { + fail: + printf (" Not enough data in NT_SIGINFO note.\n"); + return; + } + + /* Next is a pointer-aligned union of structures. On 64-bit + machines, that implies a word of padding. */ + if (gelf_getclass (core) == ELFCLASS64) + ptr += 4; + + printf (" si_signo: %d, si_errno: %d, si_code: %d\n", + si_signo, si_errno, si_code); + + if (si_code > 0) + switch (si_signo) + { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + { + uint64_t addr; + if (! buf_read_ulong (core, &ptr, end, &addr)) + goto fail; + printf (" fault address: %#" PRIx64 "\n", addr); + break; + } + default: + ; + } + else if (si_code == SI_USER) + { + int pid, uid; + if (! buf_read_int (core, &ptr, end, &pid) + || ! buf_read_int (core, &ptr, end, &uid)) + goto fail; + printf (" sender PID: %d, sender UID: %d\n", pid, uid); + } +} + +static void +handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos) +{ + Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE); + if (data == NULL) + error (EXIT_FAILURE, 0, + gettext ("cannot convert core note data: %s"), elf_errmsg (-1)); + + unsigned char const *ptr = data->d_buf; + unsigned char const *const end = data->d_buf + data->d_size; + + uint64_t count, page_size; + if (! buf_read_ulong (core, &ptr, end, &count) + || ! buf_read_ulong (core, &ptr, end, &page_size)) + { + fail: + printf (" Not enough data in NT_FILE note.\n"); + return; + } + + size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT); + uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize); + if (count > maxcount) + goto fail; + + /* Where file names are stored. */ + unsigned char const *const fstart = ptr + 3 * count * addrsize; + char const *fptr = (char *) fstart; + + printf (" %" PRId64 " files:\n", count); + for (uint64_t i = 0; i < count; ++i) + { + uint64_t mstart, mend, moffset; + if (! buf_read_ulong (core, &ptr, fstart, &mstart) + || ! buf_read_ulong (core, &ptr, fstart, &mend) + || ! buf_read_ulong (core, &ptr, fstart, &moffset)) + goto fail; + + const char *fnext = memchr (fptr, '\0', (char *) end - fptr); + if (fnext == NULL) + goto fail; + + int ct = printf (" %08" PRIx64 "-%08" PRIx64 + " %08" PRIx64 " %" PRId64, + mstart, mend, moffset * page_size, mend - mstart); + printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr); + + fptr = fnext + 1; + } +} + static void handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const char *name, const void *desc) @@ -8181,6 +9226,22 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, && !memcmp (name, "CORE", 4)) handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz, start + desc_offset); + else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0) + switch (nhdr.n_type) + { + case NT_SIGINFO: + handle_siginfo_note (ebl->elf, nhdr.n_descsz, + start + desc_offset); + break; + + case NT_FILE: + handle_file_note (ebl->elf, nhdr.n_descsz, + start + desc_offset); + break; + + default: + handle_core_note (ebl, &nhdr, name, desc); + } else handle_core_note (ebl, &nhdr, name, desc); } diff --git a/src/src/sectionhash.c b/src/src/sectionhash.c index 68d734e1..83a7cca6 100644 --- a/src/src/sectionhash.c +++ b/src/src/sectionhash.c @@ -1,28 +1,20 @@ /* Section hash table implementation. Copyright (C) 2001, 2002, 2005 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/sectionhash.h b/src/src/sectionhash.h index ba41ee8c..96da3367 100644 --- a/src/src/sectionhash.h +++ b/src/src/sectionhash.h @@ -1,27 +1,19 @@ /* Copyright (C) 2001, 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SECTIONHASH_H #define SECTIONHASH_H 1 diff --git a/src/src/size.c b/src/src/size.c index 14dafc48..0e7e41e4 100644 --- a/src/src/size.c +++ b/src/src/size.c @@ -1,28 +1,20 @@ /* Print size information from ELF file. - Copyright (C) 2000-2007,2009,2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2000-2007,2009,2012,2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2000. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -435,10 +427,9 @@ show_sysv (Elf *elf, const char *prefix, const char *fname, INTERNAL_ERROR (fullname); /* Ignore all sections which are not used at runtime. */ - if ((shdr->sh_flags & SHF_ALLOC) != 0) - maxlen = MAX (maxlen, - (int) strlen (elf_strptr (elf, shstrndx, - shdr->sh_name))); + const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); + if (name != NULL && (shdr->sh_flags & SHF_ALLOC) != 0) + maxlen = MAX (maxlen, (int) strlen (name)); } fputs_unlocked (fname, stdout); @@ -449,14 +440,6 @@ show_sysv (Elf *elf, const char *prefix, const char *fname, digits - 2, sgettext ("sysv|size"), digits, sgettext ("sysv|addr")); - const char *fmtstr; - if (radix == radix_hex) - fmtstr = "%-*s %*" PRIx64 " %*" PRIx64 "\n"; - else if (radix == radix_decimal) - fmtstr = "%-*s %*" PRId64 " %*" PRId64 "\n"; - else - fmtstr = "%-*s %*" PRIo64 " %*" PRIo64 "\n"; - /* Iterate over all sections. */ GElf_Off total = 0; while ((scn = elf_nextscn (elf, scn)) != NULL) @@ -467,7 +450,11 @@ show_sysv (Elf *elf, const char *prefix, const char *fname, /* Ignore all sections which are not used at runtime. */ if ((shdr->sh_flags & SHF_ALLOC) != 0) { - printf (fmtstr, + printf ((radix == radix_hex + ? "%-*s %*" PRIx64 " %*" PRIx64 "\n" + : (radix == radix_decimal + ? "%-*s %*" PRId64 " %*" PRId64 "\n" + : "%-*s %*" PRIo64 " %*" PRIo64 "\n")), maxlen, elf_strptr (elf, shstrndx, shdr->sh_name), digits - 2, shdr->sh_size, digits, shdr->sh_addr); @@ -498,14 +485,6 @@ show_sysv_one_line (Elf *elf) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); - const char *fmtstr; - if (radix == radix_hex) - fmtstr = "%" PRIx64 "(%s)"; - else if (radix == radix_decimal) - fmtstr = "%" PRId64 "(%s)"; - else - fmtstr = "%" PRIo64 "(%s)"; - /* Iterate over all sections. */ GElf_Off total = 0; bool first = true; @@ -523,8 +502,10 @@ show_sysv_one_line (Elf *elf) fputs_unlocked (" + ", stdout); first = false; - printf (fmtstr, shdr->sh_size, - elf_strptr (elf, shstrndx, shdr->sh_name)); + printf ((radix == radix_hex ? "%" PRIx64 "(%s)" + : (radix == radix_decimal ? "%" PRId64 "(%s)" + : "%" PRIo64 "(%s)")), + shdr->sh_size, elf_strptr (elf, shstrndx, shdr->sh_name)); total += shdr->sh_size; } @@ -619,14 +600,13 @@ show_bsd_totals (void) static void show_segments (Elf *elf, const char *fullname) { - GElf_Ehdr ehdr_mem; - GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); - if (ehdr == NULL) + size_t phnum; + if (elf_getphdrnum (elf, &phnum) != 0) INTERNAL_ERROR (fullname); GElf_Off total = 0; bool first = true; - for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt) + for (size_t cnt = 0; cnt < phnum; ++cnt) { GElf_Phdr phdr_mem; GElf_Phdr *phdr; diff --git a/src/src/stack.c b/src/src/stack.c new file mode 100644 index 00000000..c277dfd0 --- /dev/null +++ b/src/src/stack.c @@ -0,0 +1,760 @@ +/* Unwinding of frames like gstack/pstack. + Copyright (C) 2013-2014 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <assert.h> +#include <argp.h> +#include <error.h> +#include <stdlib.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <string.h> +#include <locale.h> +#include <fcntl.h> +#include ELFUTILS_HEADER(dwfl) + +#include <dwarf.h> +#include <system.h> + +/* Name and version of program. */ +static void print_version (FILE *stream, struct argp_state *state); +ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; + +/* Bug report address. */ +ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; + +/* non-printable argp options. */ +#define OPT_DEBUGINFO 0x100 +#define OPT_COREFILE 0x101 + +static bool show_activation = false; +static bool show_module = false; +static bool show_build_id = false; +static bool show_source = false; +static bool show_one_tid = false; +static bool show_quiet = false; +static bool show_raw = false; +static bool show_modules = false; +static bool show_debugname = false; +static bool show_inlines = false; + +static int maxframes = 256; + +struct frame +{ + Dwarf_Addr pc; + bool isactivation; +}; + +struct frames +{ + int frames; + int allocated; + struct frame *frame; +}; + +static Dwfl *dwfl = NULL; +static pid_t pid = 0; +static int core_fd = -1; +static Elf *core = NULL; +static const char *exec = NULL; +static char *debuginfo_path = NULL; + +static const Dwfl_Callbacks proc_callbacks = + { + .find_elf = dwfl_linux_proc_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + }; + +static const Dwfl_Callbacks core_callbacks = + { + .find_elf = dwfl_build_id_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + .debuginfo_path = &debuginfo_path, + }; + +#ifdef USE_DEMANGLE +static size_t demangle_buffer_len = 0; +static char *demangle_buffer = NULL; +#endif + +/* Whether any frames have been shown at all. Determines exit status. */ +static bool frames_shown = false; + +/* Program exit codes. All frames shown without any errors is GOOD. + Some frames shown with some non-fatal errors is an ERROR. A fatal + error or no frames shown at all is BAD. A command line USAGE exit + is generated by argp_error. */ +#define EXIT_OK 0 +#define EXIT_ERROR 1 +#define EXIT_BAD 2 +#define EXIT_USAGE 64 + +static int +get_addr_width (Dwfl_Module *mod) +{ + // Try to find the address wide if possible. + static int width = 0; + if (width == 0 && mod) + { + Dwarf_Addr bias; + Elf *elf = dwfl_module_getelf (mod, &bias); + if (elf) + { + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr) + width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16; + } + } + if (width == 0) + width = 16; + + return width; +} + +static int +module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)), + const char *name, Dwarf_Addr start, + void *arg __attribute__((unused))) +{ + /* Forces resolving of main elf and debug files. */ + Dwarf_Addr bias; + Elf *elf = dwfl_module_getelf (mod, &bias); + Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias); + + Dwarf_Addr end; + const char *mainfile; + const char *debugfile; + const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL, + NULL, &mainfile, &debugfile); + assert (strcmp (modname, name) == 0); + + int width = get_addr_width (mod); + printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n", + width, start, width, end, basename (name)); + + const unsigned char *id; + GElf_Addr id_vaddr; + int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); + if (id_len > 0) + { + printf (" ["); + do + printf ("%02" PRIx8, *id++); + while (--id_len > 0); + printf ("]\n"); + } + + if (elf != NULL) + printf (" %s\n", mainfile != NULL ? mainfile : "-"); + if (dwarf != NULL) + printf (" %s\n", debugfile != NULL ? debugfile : "-"); + + return DWARF_CB_OK; +} + +static int +frame_callback (Dwfl_Frame *state, void *arg) +{ + struct frames *frames = (struct frames *) arg; + int nr = frames->frames; + if (! dwfl_frame_pc (state, &frames->frame[nr].pc, + &frames->frame[nr].isactivation)) + return -1; + + frames->frames++; + if (frames->frames == maxframes) + return DWARF_CB_ABORT; + + if (frames->frames == frames->allocated) + { + frames->allocated *= 2; + frames->frame = realloc (frames->frame, + sizeof (struct frame) * frames->allocated); + if (frames->frame == NULL) + error (EXIT_BAD, errno, "realloc frames.frame"); + } + + return DWARF_CB_OK; +} + +static const char* +die_name (Dwarf_Die *die) +{ + Dwarf_Attribute attr; + const char *name; + name = dwarf_formstring (dwarf_attr_integrate (die, + DW_AT_MIPS_linkage_name, + &attr) + ?: dwarf_attr_integrate (die, + DW_AT_linkage_name, + &attr)); + if (name == NULL) + name = dwarf_diename (die); + + return name; +} + +static void +print_frame (int nr, Dwarf_Addr pc, bool isactivation, + Dwarf_Addr pc_adjusted, Dwfl_Module *mod, + const char *symname, Dwarf_Die *cudie, + Dwarf_Die *die) +{ + int width = get_addr_width (mod); + printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc); + + if (show_activation) + printf ("%4s", ! isactivation ? "- 1" : ""); + + if (symname != NULL) + { +#ifdef USE_DEMANGLE + // Require GNU v3 ABI by the "_Z" prefix. + if (! show_raw && symname[0] == '_' && symname[1] == 'Z') + { + int status = -1; + char *dsymname = __cxa_demangle (symname, demangle_buffer, + &demangle_buffer_len, &status); + if (status == 0) + symname = demangle_buffer = dsymname; + } +#endif + printf (" %s", symname); + } + + const char* fname; + Dwarf_Addr start; + fname = dwfl_module_info(mod, NULL, &start, + NULL, NULL, NULL, NULL, NULL); + if (show_module) + { + if (fname != NULL) + printf (" - %s", fname); + } + + if (show_build_id) + { + const unsigned char *id; + GElf_Addr id_vaddr; + int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); + if (id_len > 0) + { + printf ("\n ["); + do + printf ("%02" PRIx8, *id++); + while (--id_len > 0); + printf ("]@0x%0" PRIx64 "+0x%" PRIx64, + start, pc_adjusted - start); + } + } + + if (show_source) + { + int line, col; + const char* sname; + line = col = -1; + sname = NULL; + if (die != NULL) + { + Dwarf_Files *files; + if (dwarf_getsrcfiles (cudie, &files, NULL) == 0) + { + Dwarf_Attribute attr; + Dwarf_Word val; + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, &attr), + &val) == 0) + { + sname = dwarf_filesrc (files, val, NULL, NULL); + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line, + &attr), &val) == 0) + { + line = val; + if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column, + &attr), &val) == 0) + col = val; + } + } + } + } + else + { + Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted); + if (lineobj) + sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL); + } + + if (sname != NULL) + { + printf ("\n %s", sname); + if (line > 0) + { + printf (":%d", line); + if (col > 0) + printf (":%d", col); + } + } + } + printf ("\n"); +} + +static void +print_inline_frames (int *nr, Dwarf_Addr pc, bool isactivation, + Dwarf_Addr pc_adjusted, Dwfl_Module *mod, + const char *symname, Dwarf_Die *cudie, Dwarf_Die *die) +{ + Dwarf_Die *scopes = NULL; + int nscopes = dwarf_getscopes_die (die, &scopes); + if (nscopes > 0) + { + /* scopes[0] == die, the lowest level, for which we already have + the name. This is the actual source location where it + happened. */ + print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname, + NULL, NULL); + + /* last_scope is the source location where the next frame/function + call was done. */ + Dwarf_Die *last_scope = &scopes[0]; + for (int i = 1; i < nscopes && (maxframes == 0 || *nr < maxframes); i++) + { + Dwarf_Die *scope = &scopes[i]; + int tag = dwarf_tag (scope); + if (tag != DW_TAG_inlined_subroutine + && tag != DW_TAG_entry_point + && tag != DW_TAG_subprogram) + continue; + + symname = die_name (scope); + print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname, + cudie, last_scope); + + /* Found the "top-level" in which everything was inlined? */ + if (tag == DW_TAG_subprogram) + break; + + last_scope = scope; + } + } + free (scopes); +} + +static void +print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what) +{ + if (frames->frames > 0) + frames_shown = true; + + printf ("TID %d:\n", tid); + int frame_nr = 0; + for (int nr = 0; nr < frames->frames && (maxframes == 0 + || frame_nr < maxframes); nr++) + { + Dwarf_Addr pc = frames->frame[nr].pc; + bool isactivation = frames->frame[nr].isactivation; + Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); + + /* Get PC->SYMNAME. */ + Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); + const char *symname = NULL; + Dwarf_Die die_mem; + Dwarf_Die *die = NULL; + Dwarf_Die *cudie = NULL; + if (mod && ! show_quiet) + { + if (show_debugname) + { + Dwarf_Addr bias = 0; + Dwarf_Die *scopes = NULL; + cudie = dwfl_module_addrdie (mod, pc_adjusted, &bias); + int nscopes = dwarf_getscopes (cudie, pc_adjusted - bias, + &scopes); + + /* Find the first function-like DIE with a name in scope. */ + for (int i = 0; symname == NULL && i < nscopes; i++) + { + Dwarf_Die *scope = &scopes[i]; + int tag = dwarf_tag (scope); + if (tag == DW_TAG_subprogram + || tag == DW_TAG_inlined_subroutine + || tag == DW_TAG_entry_point) + symname = die_name (scope); + + if (symname != NULL) + { + die_mem = *scope; + die = &die_mem; + } + } + free (scopes); + } + + if (symname == NULL) + symname = dwfl_module_addrname (mod, pc_adjusted); + } + + if (show_inlines && die != NULL) + print_inline_frames (&frame_nr, pc, isactivation, pc_adjusted, mod, + symname, cudie, die); + else + print_frame (frame_nr++, pc, isactivation, pc_adjusted, mod, symname, + NULL, NULL); + } + + if (frames->frames > 0 && frame_nr == maxframes) + error (0, 0, "tid %d: shown max number of frames " + "(%d, use -n 0 for unlimited)", tid, maxframes); + else if (dwflerr != 0) + { + if (frames->frames > 0) + { + unsigned nr = frames->frames - 1; + Dwarf_Addr pc = frames->frame[nr].pc; + bool isactivation = frames->frame[nr].isactivation; + Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); + Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); + const char *mainfile = NULL; + const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL, + NULL, &mainfile, NULL); + if (modname == NULL || modname[0] == '\0') + { + if (mainfile != NULL) + modname = mainfile; + else + modname = "<unknown>"; + } + error (0, 0, "%s tid %d at 0x%" PRIx64 " in %s: %s", what, tid, + pc_adjusted, modname, dwfl_errmsg (dwflerr)); + } + else + error (0, 0, "%s tid %d: %s", what, tid, dwfl_errmsg (dwflerr)); + } +} + +static int +thread_callback (Dwfl_Thread *thread, void *thread_arg) +{ + struct frames *frames = (struct frames *) thread_arg; + pid_t tid = dwfl_thread_tid (thread); + int err = 0; + frames->frames = 0; + switch (dwfl_thread_getframes (thread, frame_callback, thread_arg)) + { + case DWARF_CB_OK: + case DWARF_CB_ABORT: + break; + case -1: + err = dwfl_errno (); + break; + default: + abort (); + } + print_frames (frames, tid, err, "dwfl_thread_getframes"); + return DWARF_CB_OK; +} + +static void +print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) +{ + fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); +} + +static error_t +parse_opt (int key, char *arg __attribute__ ((unused)), + struct argp_state *state) +{ + switch (key) + { + case 'p': + pid = atoi (arg); + if (pid == 0) + argp_error (state, N_("-p PID should be a positive process id.")); + break; + + case OPT_COREFILE: + core_fd = open (arg, O_RDONLY); + if (core_fd < 0) + error (EXIT_BAD, errno, N_("Cannot open core file '%s'"), arg); + elf_version (EV_CURRENT); + core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL); + if (core == NULL) + error (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1)); + break; + + case 'e': + exec = arg; + break; + + case OPT_DEBUGINFO: + debuginfo_path = arg; + break; + + case 'm': + show_module = true; + break; + + case 's': + show_source = true; + break; + + case 'a': + show_activation = true; + break; + + case 'd': + show_debugname = true; + break; + + case 'i': + show_inlines = show_debugname = true; + break; + + case 'v': + show_activation = show_source = show_module = show_debugname = true; + show_inlines = true; + break; + + case 'b': + show_build_id = true; + break; + + case 'q': + show_quiet = true; + break; + + case 'r': + show_raw = true; + break; + + case '1': + show_one_tid = true; + break; + + case 'n': + maxframes = atoi (arg); + if (maxframes < 0) + { + argp_error (state, N_("-n MAXFRAMES should be 0 or higher.")); + return EINVAL; + } + break; + + case 'l': + show_modules = true; + break; + + case ARGP_KEY_END: + if (core == NULL && exec != NULL) + argp_error (state, + N_("-e EXEC needs a core given by --core.")); + + if (pid == 0 && show_one_tid == true) + argp_error (state, + N_("-1 needs a thread id given by -p.")); + + if ((pid == 0 && core == NULL) || (pid != 0 && core != NULL)) + argp_error (state, + N_("One of -p PID or --core COREFILE should be given.")); + + if (pid != 0) + { + dwfl = dwfl_begin (&proc_callbacks); + if (dwfl == NULL) + error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); + + int err = dwfl_linux_proc_report (dwfl, pid); + if (err < 0) + error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %d: %s", pid, + dwfl_errmsg (-1)); + else if (err > 0) + error (EXIT_BAD, err, "dwfl_linux_proc_report pid %d", pid); + } + + if (core != NULL) + { + dwfl = dwfl_begin (&core_callbacks); + if (dwfl == NULL) + error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); + if (dwfl_core_file_report (dwfl, core, exec) < 0) + error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1)); + } + + if (dwfl_report_end (dwfl, NULL, NULL) != 0) + error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1)); + + if (pid != 0) + { + int err = dwfl_linux_proc_attach (dwfl, pid, false); + if (err < 0) + error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid, + dwfl_errmsg (-1)); + else if (err > 0) + error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid); + } + + if (core != NULL) + { + if (dwfl_core_file_attach (dwfl, core) < 0) + error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1)); + } + + /* Makes sure we are properly attached. */ + if (dwfl_pid (dwfl) < 0) + error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1)); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +int +main (int argc, char **argv) +{ + /* We use no threads here which can interfere with handling a stream. */ + __fsetlocking (stdin, FSETLOCKING_BYCALLER); + __fsetlocking (stdout, FSETLOCKING_BYCALLER); + __fsetlocking (stderr, FSETLOCKING_BYCALLER); + + /* Set locale. */ + (void) setlocale (LC_ALL, ""); + + const struct argp_option options[] = + { + { NULL, 0, NULL, 0, N_("Input selection options:"), 0 }, + { "pid", 'p', "PID", 0, + N_("Show stack of process PID"), 0 }, + { "core", OPT_COREFILE, "COREFILE", 0, + N_("Show stack found in COREFILE"), 0 }, + { "executable", 'e', "EXEC", 0, N_("(optional) EXECUTABLE that produced COREFILE"), 0 }, + { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0, + N_("Search path for separate debuginfo files"), 0 }, + + { NULL, 0, NULL, 0, N_("Output selection options:"), 0 }, + { "activation", 'a', NULL, 0, + N_("Additionally show frame activation"), 0 }, + { "debugname", 'd', NULL, 0, + N_("Additionally try to lookup DWARF debuginfo name for frame address"), + 0 }, + { "inlines", 'i', NULL, 0, + N_("Additionally show inlined function frames using DWARF debuginfo if available (implies -d)"), 0 }, + { "module", 'm', NULL, 0, + N_("Additionally show module file information"), 0 }, + { "source", 's', NULL, 0, + N_("Additionally show source file information"), 0 }, + { "verbose", 'v', NULL, 0, + N_("Show all additional information (activation, debugname, inlines, module and source)"), 0 }, + { "quiet", 'q', NULL, 0, + N_("Do not resolve address to function symbol name"), 0 }, + { "raw", 'r', NULL, 0, + N_("Show raw function symbol names, do not try to demangle names"), 0 }, + { "build-id", 'b', NULL, 0, + N_("Show module build-id, load address and pc offset"), 0 }, + { NULL, '1', NULL, 0, + N_("Show the backtrace of only one thread"), 0 }, + { NULL, 'n', "MAXFRAMES", 0, + N_("Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"), 0 }, + { "list-modules", 'l', NULL, 0, + N_("Show module memory map with build-id, elf and debug files detected"), 0 }, + { NULL, 0, NULL, 0, NULL, 0 } + }; + + const struct argp argp = + { + .options = options, + .parser = parse_opt, + .doc = N_("Print a stack for each thread in a process or core file.\v\ +Program exits with return code 0 if all frames were shown without \ +any errors. If some frames were shown, but there were some non-fatal \ +errors, possibly causing an incomplete backtrace, the program exits \ +with return code 1. If no frames could be shown, or a fatal error \ +occured the program exits with return code 2. If the program was \ +invoked with bad or missing arguments it will exit with return code 64.") + }; + + argp_parse (&argp, argc, argv, 0, NULL, NULL); + + if (show_modules) + { + printf ("PID %d - %s module memory map\n", dwfl_pid (dwfl), + pid != 0 ? "process" : "core"); + if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0) + error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); + } + + struct frames frames; + /* When maxframes is zero, then 2048 is just the initial allocation + that will be increased using realloc in framecallback (). */ + frames.allocated = maxframes == 0 ? 2048 : maxframes; + frames.frames = 0; + frames.frame = malloc (sizeof (struct frame) * frames.allocated); + if (frames.frame == NULL) + error (EXIT_BAD, errno, "malloc frames.frame"); + + if (show_one_tid) + { + int err = 0; + switch (dwfl_getthread_frames (dwfl, pid, frame_callback, &frames)) + { + case DWARF_CB_OK: + case DWARF_CB_ABORT: + break; + case -1: + err = dwfl_errno (); + break; + default: + abort (); + } + print_frames (&frames, pid, err, "dwfl_getthread_frames"); + } + else + { + printf ("PID %d - %s\n", dwfl_pid (dwfl), pid != 0 ? "process" : "core"); + switch (dwfl_getthreads (dwfl, thread_callback, &frames)) + { + case DWARF_CB_OK: + case DWARF_CB_ABORT: + break; + case -1: + error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1)); + break; + default: + abort (); + } + } + free (frames.frame); + dwfl_end (dwfl); + + if (core != NULL) + elf_end (core); + + if (core_fd != -1) + close (core_fd); + +#ifdef USE_DEMANGLE + free (demangle_buffer); +#endif + + if (! frames_shown) + error (EXIT_BAD, 0, N_("Couldn't show any frames.")); + + return error_message_count != 0 ? EXIT_ERROR : EXIT_OK; +} diff --git a/src/src/strings.c b/src/src/strings.c index 442901e5..f60e4b4d 100644 --- a/src/src/strings.c +++ b/src/src/strings.c @@ -1,28 +1,20 @@ /* Print the strings of printable characters in files. - Copyright (C) 2005-2010, 2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2005-2010, 2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2005. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -124,8 +116,15 @@ static bool char_7bit; /* True if file names should be printed before strings. */ static bool print_file_name; -/* Location print format string. */ -static const char *locfmt; +/* Radix for printed numbers. */ +static enum +{ + radix_none = 0, + radix_decimal, + radix_hex, + radix_octal +} radix = radix_none; + /* Page size in use. */ static size_t ps; @@ -287,16 +286,16 @@ parse_opt (int key, char *arg, switch (arg[0]) { case 'd': - locfmt = "%7" PRId64 " "; + radix = radix_decimal; break; case 'o': octfmt: - locfmt = "%7" PRIo64 " "; + radix = radix_octal; break; case 'x': - locfmt = "%7" PRIx64 " "; + radix = radix_hex; break; default: @@ -363,8 +362,11 @@ process_chunk_mb (const char *fname, const unsigned char *buf, off64_t to, fputs_unlocked (": ", stdout); } - if (unlikely (locfmt != NULL)) - printf (locfmt, (int64_t) to - len - (buf - start)); + if (unlikely (radix != radix_none)) + printf ((radix == radix_octal ? "%7" PRIo64 " " + : (radix == radix_decimal ? "%7" PRId64 " " + : "%7" PRIx64 " ")), + (int64_t) to - len - (buf - start)); if (unlikely (*unprinted != NULL)) { @@ -428,8 +430,11 @@ process_chunk (const char *fname, const unsigned char *buf, off64_t to, fputs_unlocked (": ", stdout); } - if (likely (locfmt != NULL)) - printf (locfmt, (int64_t) to - len - (buf - start)); + if (likely (radix != radix_none)) + printf ((radix == radix_octal ? "%7" PRIo64 " " + : (radix == radix_decimal ? "%7" PRId64 " " + : "%7" PRIx64 " ")), + (int64_t) to - len - (buf - start)); if (unlikely (*unprinted != NULL)) { @@ -460,13 +465,6 @@ process_chunk (const char *fname, const unsigned char *buf, off64_t to, static void * map_file (int fd, off64_t start_off, off64_t fdlen, size_t *map_sizep) { -#if _MUDFLAP - (void) fd; - (void) start_off; - (void) fdlen; - (void) map_sizep; - return MAP_FAILED; -#else /* Maximum size we mmap. We use an #ifdef to avoid overflows on 32-bit machines. 64-bit machines these days do not have usable address spaces larger than about 43 bits. Not that any file @@ -508,7 +506,6 @@ map_file (int fd, off64_t start_off, off64_t fdlen, size_t *map_sizep) *map_sizep = map_size; return mem; -#endif } diff --git a/src/src/strip.c b/src/src/strip.c index 78f683a8..2b217996 100644 --- a/src/src/strip.c +++ b/src/src/strip.c @@ -1,28 +1,20 @@ /* Discard section not used at runtime from object files. - Copyright (C) 2000-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2000-2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2000. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> @@ -440,6 +432,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, Elf_Data debuglink_crc_data; bool any_symtab_changes = false; Elf_Data *shstrtab_data = NULL; + void *debuglink_buf = NULL; /* Create the full name of the file. */ if (prefix != NULL) @@ -509,6 +502,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); + /* Get the number of phdrs in the old file. */ + size_t phnum; + if (elf_getphdrnum (elf, &phnum) != 0) + error (EXIT_FAILURE, 0, gettext ("cannot get number of phdrs")); + /* We now create a new ELF descriptor for the same file. We construct it almost exactly in the same way with some information dropped. */ @@ -520,7 +518,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0) || (ehdr->e_type != ET_REL - && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0))) + && unlikely (gelf_newphdr (newelf, phnum) == 0))) { error (0, 0, gettext ("cannot create new file '%s': %s"), output_fname, elf_errmsg (-1)); @@ -529,7 +527,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* Copy over the old program header if needed. */ if (ehdr->e_type != ET_REL) - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) + for (cnt = 0; cnt < phnum; ++cnt) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem); @@ -544,7 +542,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL); if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0) || (ehdr->e_type != ET_REL - && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0))) + && unlikely (gelf_newphdr (debugelf, phnum) == 0))) { error (0, 0, gettext ("cannot create new file '%s': %s"), debug_fname, elf_errmsg (-1)); @@ -553,7 +551,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* Copy over the old program header if needed. */ if (ehdr->e_type != ET_REL) - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) + for (cnt = 0; cnt < phnum; ++cnt) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem); @@ -572,6 +570,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, goto fail_close; } + if (shstrndx >= shnum) + goto illformed; + +#define elf_assert(test) do { if (!(test)) goto illformed; } while (0) + /* Storage for section information. We leave room for two more entries since we unconditionally create a section header string table. Maybe some weird tool created an ELF file without one. @@ -593,7 +596,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { /* This should always be true (i.e., there should not be any holes in the numbering). */ - assert (elf_ndxscn (scn) == cnt); + elf_assert (elf_ndxscn (scn) == cnt); shdr_info[cnt].scn = scn; @@ -606,6 +609,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, shdr_info[cnt].shdr.sh_name); if (shdr_info[cnt].name == NULL) { + illformed: error (0, 0, gettext ("illformed file '%s'"), fname); goto fail_close; } @@ -615,6 +619,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* Remember the shdr.sh_link value. */ shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link; + if (shdr_info[cnt].old_sh_link >= shnum) + goto illformed; /* Sections in files other than relocatable object files which are not loaded can be freely moved by us. In relocatable @@ -627,7 +633,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, appropriate reference. */ if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX)) { - assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0); + elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0); shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt; } else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP)) @@ -644,7 +650,12 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, for (inner = 1; inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word); ++inner) - shdr_info[grpref[inner]].group_idx = cnt; + { + if (grpref[inner] < shnum) + shdr_info[grpref[inner]].group_idx = cnt; + else + goto illformed; + } if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0)) /* If the section group contains only one element and this @@ -655,7 +666,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, } else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)) { - assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0); + elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0); shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt; } @@ -663,7 +674,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, discarded right away. */ if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0) { - assert (shdr_info[cnt].group_idx != 0); + elf_assert (shdr_info[cnt].group_idx != 0); if (shdr_info[shdr_info[cnt].group_idx].idx == 0) { @@ -739,10 +750,14 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { /* If a relocation section is marked as being removed make sure the section it is relocating is removed, too. */ - if ((shdr_info[cnt].shdr.sh_type == SHT_REL + if (shdr_info[cnt].shdr.sh_type == SHT_REL || shdr_info[cnt].shdr.sh_type == SHT_RELA) - && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) - shdr_info[cnt].idx = 1; + { + if (shdr_info[cnt].shdr.sh_info >= shnum) + goto illformed; + else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0) + shdr_info[cnt].idx = 1; + } /* If a group section is marked as being removed make sure all the sections it contains are being removed, too. */ @@ -786,7 +801,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, if (shdr_info[cnt].symtab_idx != 0 && shdr_info[shdr_info[cnt].symtab_idx].data == NULL) { - assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB); + elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB); shdr_info[shdr_info[cnt].symtab_idx].data = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn, @@ -826,6 +841,9 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, else if (scnidx == SHN_XINDEX) scnidx = xndx; + if (scnidx >= shnum) + goto illformed; + if (shdr_info[scnidx].idx == 0) /* This symbol table has a real symbol in a discarded section. So preserve the @@ -856,11 +874,15 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, } /* Handle references through sh_info. */ - if (SH_INFO_LINK_P (&shdr_info[cnt].shdr) - && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) + if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)) { - shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1; - changes |= shdr_info[cnt].shdr.sh_info < cnt; + if (shdr_info[cnt].shdr.sh_info >= shnum) + goto illformed; + else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0) + { + shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1; + changes |= shdr_info[cnt].shdr.sh_info < cnt; + } } /* Mark the section as investigated. */ @@ -1002,7 +1024,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"), elf_errmsg (-1)); - assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx); + elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx); /* Add this name to the section header string table. */ shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0); @@ -1039,7 +1061,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, error (EXIT_FAILURE, 0, gettext ("while create section header section: %s"), elf_errmsg (-1)); - assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx); + elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx); shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn); if (shdr_info[cnt].data == NULL) @@ -1054,7 +1076,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, shdr_info[cnt].data->d_align = 4; shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size = crc_offset + 4; - shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size); + debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size); + shdr_info[cnt].data->d_buf = debuglink_buf; strcpy (shdr_info[cnt].data->d_buf, debug_basename); @@ -1095,7 +1118,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, error (EXIT_FAILURE, 0, gettext ("while create section header section: %s"), elf_errmsg (-1)); - assert (elf_ndxscn (shdr_info[cnt].newscn) == idx); + elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx); /* Finalize the string table and fill in the correct indices in the section headers. */ @@ -1185,20 +1208,20 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn, NULL); - assert ((versiondata->d_size / sizeof (Elf32_Word)) + elf_assert ((versiondata->d_size / sizeof (Elf32_Word)) >= shdr_info[cnt].data->d_size / elsize); } if (shdr_info[cnt].version_idx != 0) { - assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM); + elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM); /* This section has associated version information. We have to modify that information, too. */ versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn, NULL); - assert ((versiondata->d_size / sizeof (GElf_Versym)) + elf_assert ((versiondata->d_size / sizeof (GElf_Versym)) >= shdr_info[cnt].data->d_size / elsize); } @@ -1253,7 +1276,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, sec = shdr_info[sym->st_shndx].idx; else { - assert (shndxdata != NULL); + elf_assert (shndxdata != NULL); sec = shdr_info[xshndx].idx; } @@ -1274,7 +1297,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, nxshndx = sec; } - assert (sec < SHN_LORESERVE || shndxdata != NULL); + elf_assert (sec < SHN_LORESERVE || shndxdata != NULL); if ((inner != destidx || nshndx != sym->st_shndx || (shndxdata != NULL && nxshndx != xshndx)) @@ -1301,9 +1324,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { size_t sidx = (sym->st_shndx != SHN_XINDEX ? sym->st_shndx : xshndx); - assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION - || (shdr_info[sidx].shdr.sh_type == SHT_GROUP - && shdr_info[sidx].shdr.sh_info == inner)); + elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION + || ((shdr_info[sidx].shdr.sh_type + == SHT_GROUP) + && (shdr_info[sidx].shdr.sh_info + == inner))); } } @@ -1491,11 +1516,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { GElf_Sym sym_mem; GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem); - assert (sym != NULL); + elf_assert (sym != NULL); const char *name = elf_strptr (elf, strshndx, sym->st_name); - assert (name != NULL); + elf_assert (name != NULL); size_t hidx = elf_hash (name) % nbucket; if (bucket[hidx] == 0) @@ -1514,8 +1539,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, else { /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */ - assert (shdr_info[cnt].shdr.sh_entsize - == sizeof (Elf64_Xword)); + elf_assert (shdr_info[cnt].shdr.sh_entsize + == sizeof (Elf64_Xword)); Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf; @@ -1545,11 +1570,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { GElf_Sym sym_mem; GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem); - assert (sym != NULL); + elf_assert (sym != NULL); const char *name = elf_strptr (elf, strshndx, sym->st_name); - assert (name != NULL); + elf_assert (name != NULL); size_t hidx = elf_hash (name) % nbucket; if (bucket[hidx] == 0) @@ -2021,6 +2046,9 @@ while computing checksum for debug information")); free (shdr_info[cnt].debug_data->d_buf); } + /* Free data we allocated for the .gnu_debuglink section. */ + free (debuglink_buf); + /* Free the memory. */ if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC) free (shdr_info); diff --git a/src/src/symbolhash.c b/src/src/symbolhash.c index 670cf056..3fd96499 100644 --- a/src/src/symbolhash.c +++ b/src/src/symbolhash.c @@ -1,28 +1,20 @@ /* Symbol hash table implementation. Copyright (C) 2001, 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/symbolhash.h b/src/src/symbolhash.h index 54b95397..062dadec 100644 --- a/src/src/symbolhash.h +++ b/src/src/symbolhash.h @@ -1,27 +1,19 @@ /* Copyright (C) 2001, 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SYMBOLHASH_H #define SYMBOLHASH_H 1 diff --git a/src/src/unaligned.h b/src/src/unaligned.h index ad7c55a5..29166530 100644 --- a/src/src/unaligned.h +++ b/src/src/unaligned.h @@ -1,28 +1,20 @@ /* Unaligned memory access functionality. Copyright (C) 2000, 2001, 2002, 2003, 2008 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _UNALIGNED_H #define _UNALIGNED_H 1 diff --git a/src/src/unstrip.c b/src/src/unstrip.c index f62010a3..989ac5ff 100644 --- a/src/src/unstrip.c +++ b/src/src/unstrip.c @@ -1,28 +1,20 @@ /* Combine stripped files with separate symbols and debug information. - Copyright (C) 2007-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + Copyright (C) 2007-2012, 2014 Red Hat, Inc. + This file is part of elfutils. Written by Roland McGrath <roland@redhat.com>, 2007. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* TODO: @@ -90,6 +82,9 @@ static const struct argp_option options[] = N_("Apply relocations to section contents in ET_REL files"), 0 }, { "list-only", 'n', NULL, 0, N_("Only list module and file names, build IDs"), 0 }, + { "force", 'F', NULL, 0, + N_("Force combining files even if some ELF headers don't seem to match"), + 0 }, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -105,6 +100,7 @@ struct arg_info bool modnames; bool match_files; bool relocate; + bool force; }; /* Handle program arguments. */ @@ -155,6 +151,9 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'R': info->relocate = true; break; + case 'F': + info->force = true; + break; case ARGP_KEY_ARGS: case ARGP_KEY_NO_ARGS: @@ -242,7 +241,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ #define ELF_CHECK(call, msg) \ do \ { \ - if (!(call)) \ + if (unlikely (!(call))) \ error (EXIT_FAILURE, 0, msg, elf_errmsg (-1)); \ } while (0) @@ -258,13 +257,17 @@ copy_elf (Elf *outelf, Elf *inelf) ELF_CHECK (gelf_update_ehdr (outelf, ehdr), _("cannot copy ELF header: %s")); - if (ehdr->e_phnum > 0) + size_t phnum; + ELF_CHECK (elf_getphdrnum (inelf, &phnum) == 0, + _("cannot get number of program headers: %s")); + + if (phnum > 0) { - ELF_CHECK (gelf_newphdr (outelf, ehdr->e_phnum), + ELF_CHECK (gelf_newphdr (outelf, phnum), _("cannot create program headers: %s")); GElf_Phdr phdr_mem; - for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i) + for (size_t i = 0; i < phnum; ++i) ELF_CHECK (gelf_update_phdr (outelf, i, gelf_getphdr (inelf, i, &phdr_mem)), _("cannot copy program header: %s")); @@ -1126,10 +1129,11 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, && (sec->shdr.sh_type == undo_sec->shdr.sh_type || (sec->shdr.sh_type == SHT_PROGBITS && undo_sec->shdr.sh_type == SHT_NOBITS)) - && sec->shdr.sh_size < undo_sec->shdr.sh_size + && sec->shdr.sh_size <= undo_sec->shdr.sh_size && (!strcmp (sec->name, ".bss") || !strcmp (sec->name, ".sbss")) - && (split_bss = sec) > sections))) + && (sec->shdr.sh_size == undo_sec->shdr.sh_size + || (split_bss = sec) > sections)))) { sec->outscn = undo_sec->outscn; undo_sec = NULL; @@ -1823,12 +1827,16 @@ more sections in stripped file than debug file -- arguments reversed?")); } while (skip_reloc); - if (stripped_ehdr->e_phnum > 0) - ELF_CHECK (gelf_newphdr (unstripped, stripped_ehdr->e_phnum), + size_t phnum; + ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0, + _("cannot get number of program headers: %s")); + + if (phnum > 0) + ELF_CHECK (gelf_newphdr (unstripped, phnum), _("cannot create program headers: %s")); /* Copy each program header from the stripped file. */ - for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i) + for (size_t i = 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem); @@ -1863,11 +1871,15 @@ handle_file (const char *output_file, bool create_dirs, Elf *stripped, const GElf_Ehdr *stripped_ehdr, Elf *unstripped) { + size_t phnum; + ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0, + _("cannot get number of program headers: %s")); + /* Determine the address bias between the debuginfo file and the main file, which may have been modified by prelinking. */ GElf_Addr bias = 0; if (unstripped != NULL) - for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i) + for (size_t i = 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem); @@ -1943,9 +1955,20 @@ open_file (const char *file, bool writable) /* Handle a pair of files we need to open by name. */ static void -handle_explicit_files (const char *output_file, bool create_dirs, +handle_explicit_files (const char *output_file, bool create_dirs, bool force, const char *stripped_file, const char *unstripped_file) { + + /* Warn, and exit if not forced to continue, if some ELF header + sanity check for the stripped and unstripped files failed. */ + void warn (const char *msg) + { + error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.", + force ? _("WARNING: ") : "", + stripped_file, unstripped_file, msg, + force ? "" : _(", use --force")); + } + int stripped_fd = open_file (stripped_file, false); Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL); GElf_Ehdr stripped_ehdr; @@ -1964,12 +1987,18 @@ handle_explicit_files (const char *output_file, bool create_dirs, ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr), _("cannot create ELF descriptor: %s")); - if (memcmp (stripped_ehdr.e_ident, unstripped_ehdr.e_ident, EI_NIDENT) - || stripped_ehdr.e_type != unstripped_ehdr.e_type - || stripped_ehdr.e_machine != unstripped_ehdr.e_machine - || stripped_ehdr.e_phnum != unstripped_ehdr.e_phnum) - error (EXIT_FAILURE, 0, _("'%s' and '%s' do not seem to match"), - stripped_file, unstripped_file); + if (memcmp (stripped_ehdr.e_ident, + unstripped_ehdr.e_ident, EI_NIDENT) != 0) + warn (_("ELF header identification (e_ident) different")); + + if (stripped_ehdr.e_type != unstripped_ehdr.e_type) + warn (_("ELF header type (e_type) different")); + + if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine) + warn (_("ELF header machine type (e_machine) different")); + + if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum) + warn (_("stripped program header (e_phnum) smaller than unstripped")); } handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped); @@ -1984,7 +2013,7 @@ handle_explicit_files (const char *output_file, bool create_dirs, /* Handle a pair of files opened implicitly by libdwfl for one module. */ static void -handle_dwfl_module (const char *output_file, bool create_dirs, +handle_dwfl_module (const char *output_file, bool create_dirs, bool force, Dwfl_Module *mod, bool all, bool ignore, bool relocate) { GElf_Addr bias; @@ -2056,7 +2085,7 @@ handle_dwfl_module (const char *output_file, bool create_dirs, (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, &stripped_file, &unstripped_file); - handle_explicit_files (output_file, create_dirs, + handle_explicit_files (output_file, create_dirs, force, stripped_file, unstripped_file); return; } @@ -2076,7 +2105,7 @@ handle_dwfl_module (const char *output_file, bool create_dirs, /* Handle one module being written to the output directory. */ static void -handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, +handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force, bool all, bool ignore, bool modnames, bool relocate) { if (! modnames) @@ -2097,7 +2126,7 @@ handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, if (asprintf (&output_file, "%s/%s", output_dir, modnames ? name : file) < 0) error (EXIT_FAILURE, 0, _("memory exhausted")); - handle_dwfl_module (output_file, true, mod, all, ignore, relocate); + handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate); } @@ -2209,12 +2238,12 @@ handle_implicit_modules (const struct arg_info *info) { if (next (offset) != 0) error (EXIT_FAILURE, 0, _("matched more than one module")); - handle_dwfl_module (info->output_file, false, mmi.found, + handle_dwfl_module (info->output_file, false, info->force, mmi.found, info->all, info->ignore, info->relocate); } else do - handle_output_dir_module (info->output_dir, mmi.found, + handle_output_dir_module (info->output_dir, mmi.found, info->force, info->all, info->ignore, info->modnames, info->relocate); while ((offset = next (offset)) > 0); @@ -2304,11 +2333,12 @@ or - if no debuginfo was found, or . if FILE contains the debug information.\ char *file; if (asprintf (&file, "%s/%s", info.output_dir, info.args[0]) < 0) error (EXIT_FAILURE, 0, _("memory exhausted")); - handle_explicit_files (file, true, info.args[0], info.args[1]); + handle_explicit_files (file, true, info.force, + info.args[0], info.args[1]); free (file); } else - handle_explicit_files (info.output_file, false, + handle_explicit_files (info.output_file, false, info.force, info.args[0], info.args[1]); } else diff --git a/src/src/versionhash.c b/src/src/versionhash.c index 6126eb95..cc4d2833 100644 --- a/src/src/versionhash.c +++ b/src/src/versionhash.c @@ -1,28 +1,20 @@ /* Version symbol hash table implementation. Copyright (C) 2001, 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/versionhash.h b/src/src/versionhash.h index 63ca1145..4434e055 100644 --- a/src/src/versionhash.h +++ b/src/src/versionhash.h @@ -1,27 +1,19 @@ /* Copyright (C) 2001, 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2001. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef VERSIONHASH_H #define VERSIONHASH_H 1 diff --git a/src/src/xelf.h b/src/src/xelf.h index 21c7193a..f292327d 100644 --- a/src/src/xelf.h +++ b/src/src/xelf.h @@ -1,28 +1,20 @@ /* Macros to enable writing native and generic ELF access code. Copyright (C) 2003 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2003. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> diff --git a/src/src/ylwrap b/src/src/ylwrap deleted file mode 100644 index b77a9ebb..00000000 --- a/src/src/ylwrap +++ /dev/null @@ -1,154 +0,0 @@ -#! /bin/sh -# ylwrap - wrapper for lex/yacc invocations. -# Copyright 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc. -# Written by Tom Tromey <tromey@cygnus.com>. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Usage: -# ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... -# * INPUT is the input file -# * OUTPUT is file PROG generates -# * DESIRED is file we actually want -# * PROGRAM is program to run -# * ARGS are passed to PROG -# Any number of OUTPUT,DESIRED pairs may be used. - -# The input. -input="$1" -shift -case "$input" in - [\\/]* | ?:[\\/]*) - # Absolute path; do nothing. - ;; - *) - # Relative path. Make it absolute. - input="`pwd`/$input" - ;; -esac - -pairlist= -while test "$#" -ne 0; do - if test "$1" = "--"; then - shift - break - fi - pairlist="$pairlist $1" - shift -done - -# The program to run. -prog="$1" -shift -# Make any relative path in $prog absolute. -case "$prog" in - [\\/]* | ?:[\\/]*) ;; - *[\\/]*) prog="`pwd`/$prog" ;; -esac - -# FIXME: add hostname here for parallel makes that run commands on -# other machines. But that might take us over the 14-char limit. -dirname=ylwrap$$ -trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 -mkdir $dirname || exit 1 - -cd $dirname - -$prog ${1+"$@"} "$input" -status=$? - -if test $status -eq 0; then - set X $pairlist - shift - first=yes - # Since DOS filename conventions don't allow two dots, - # the DOS version of Bison writes out y_tab.c instead of y.tab.c - # and y_tab.h instead of y.tab.h. Test to see if this is the case. - y_tab_nodot="no" - if test -f y_tab.c || test -f y_tab.h; then - y_tab_nodot="yes" - fi - - # The directory holding the input. - input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` - # Quote $INPUT_DIR so we can use it in a regexp. - # FIXME: really we should care about more than `.' and `\'. - input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'` - - while test "$#" -ne 0; do - from="$1" - # Handle y_tab.c and y_tab.h output by DOS - if test $y_tab_nodot = "yes"; then - if test $from = "y.tab.c"; then - from="y_tab.c" - else - if test $from = "y.tab.h"; then - from="y_tab.h" - fi - fi - fi - if test -f "$from"; then - # If $2 is an absolute path name, then just use that, - # otherwise prepend `../'. - case "$2" in - [\\/]* | ?:[\\/]*) target="$2";; - *) target="../$2";; - esac - - # Edit out `#line' or `#' directives. - # - # We don't want the resulting debug information to point at - # an absolute srcdir; it is better for it to just mention the - # .y file with no path. - # - # We want to use the real output file name, not yy.lex.c for - # instance. - # - # We want the include guards to be adjusted too. - FROM=`echo "$from" | sed \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ - -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` - TARGET=`echo "$2" | sed \ - -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ - -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` - sed "/^#/{s,$input_rx,,;s,$from,$2,;s,$FORM,$TO,;}" "$from" >"$target" || - status=$? - else - # A missing file is only an error for the first file. This - # is a blatant hack to let us support using "yacc -d". If -d - # is not specified, we don't want an error when the header - # file is "missing". - if test $first = yes; then - status=1 - fi - fi - shift - shift - first=no - done -else - status=$? -fi - -# Remove the directory. -cd .. -rm -rf $dirname - -exit $status |