diff options
Diffstat (limited to 'poky/meta/recipes-devtools/binutils')
5 files changed, 1951 insertions, 9 deletions
diff --git a/poky/meta/recipes-devtools/binutils/binutils-2.36.inc b/poky/meta/recipes-devtools/binutils/binutils-2.36.inc index 296829188..d54e2a345 100644 --- a/poky/meta/recipes-devtools/binutils/binutils-2.36.inc +++ b/poky/meta/recipes-devtools/binutils/binutils-2.36.inc @@ -10,22 +10,16 @@ LIC_FILES_CHKSUM="\ file://bfd/COPYING;md5=d32239bcb673463ab874e80d47fae504\ " -def binutils_branch_version(d): - pvsplit = d.getVar('PV').split('.') - return pvsplit[0] + "_" + pvsplit[1] - # When upgrading to 2.37, please make sure there is no trailing .0, so # that upstream version check can work correctly. PV = "2.36.1" CVE_VERSION = "2.36.1" -BINUPV = "${@binutils_branch_version(d)}" -#BRANCH = "binutils-${BINUPV}-branch" -BRANCH ?= "binutils-2_36-branch" +SRCBRANCH ?= "binutils-2_36-branch" UPSTREAM_CHECK_GITTAGREGEX = "binutils-(?P<pver>\d+_(\d_?)*)" SRCREV ?= "7651a4871c225925ffdfda0a8c91a6ed370cd9a1" -BINUTILS_GIT_URI ?= "git://sourceware.org/git/binutils-gdb.git;branch=${BRANCH};protocol=git" +BINUTILS_GIT_URI ?= "git://sourceware.org/git/binutils-gdb.git;branch=${SRCBRANCH};protocol=git" SRC_URI = "\ ${BINUTILS_GIT_URI} \ file://0004-configure-widen-the-regexp-for-SH-architectures.patch \ @@ -41,5 +35,8 @@ SRC_URI = "\ file://0014-Fix-rpath-in-libtool-when-sysroot-is-enabled.patch \ file://0015-sync-with-OE-libtool-changes.patch \ file://0016-Check-for-clang-before-checking-gcc-version.patch \ + file://0017-Add-support-for-the-DW_FORM_strx-forms-to-the-BFD-li.patch \ + file://0018-Add-DWARF-5-support-in-gold.patch \ + file://CVE-2021-20197.patch \ " S = "${WORKDIR}/git" diff --git a/poky/meta/recipes-devtools/binutils/binutils/0017-Add-support-for-the-DW_FORM_strx-forms-to-the-BFD-li.patch b/poky/meta/recipes-devtools/binutils/binutils/0017-Add-support-for-the-DW_FORM_strx-forms-to-the-BFD-li.patch new file mode 100644 index 000000000..b4880e0d1 --- /dev/null +++ b/poky/meta/recipes-devtools/binutils/binutils/0017-Add-support-for-the-DW_FORM_strx-forms-to-the-BFD-li.patch @@ -0,0 +1,183 @@ +From a50c11a7a47b26e6a3e095dfb72aa2e465919fb6 Mon Sep 17 00:00:00 2001 +From: Nick Clifton <nickc@redhat.com> +Date: Fri, 5 Mar 2021 17:06:59 +0000 +Subject: [PATCH] Add support for the DW_FORM_strx* forms to the BFD library. + + PR 27521 + * dwarf2.c (is_str_attr): Add DW_FORM_strx* forms. + (read_indexed_string): Placeholder function. + (read_attribute_value): Handle DW_FORM_strx* and DW_FORM_addrx* + forms. + +Upstream-Status: Backport [https://sourceware.org/bugzilla/show_bug.cgi?id=27521] +Signed-off-by: Khem Raj <raj.khem@gmail.com> +--- + bfd/dwarf2.c | 105 ++++++++++++++++++++++++++++++++------------------- + 1 file changed, 67 insertions(+), 38 deletions(-) + +diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c +index 5651696c0f7..5ffcd93f54c 100644 +--- a/bfd/dwarf2.c ++++ b/bfd/dwarf2.c +@@ -1160,8 +1160,23 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash, + static inline bfd_boolean + is_str_attr (enum dwarf_form form) + { +- return (form == DW_FORM_string || form == DW_FORM_strp +- || form == DW_FORM_line_strp || form == DW_FORM_GNU_strp_alt); ++ return (form == DW_FORM_string ++ || form == DW_FORM_strp ++ || form == DW_FORM_strx ++ || form == DW_FORM_strx1 ++ || form == DW_FORM_strx2 ++ || form == DW_FORM_strx3 ++ || form == DW_FORM_strx4 ++ || form == DW_FORM_line_strp ++ || form == DW_FORM_GNU_strp_alt); ++} ++ ++static const char * ++read_indexed_string (bfd_uint64_t index ATTRIBUTE_UNUSED, ++ struct comp_unit * unit ATTRIBUTE_UNUSED) ++{ ++ /* FIXME: Add support for indexed strings. */ ++ return "<indexed strings not yet supported>"; + } + + /* Read and fill in the value of attribute ATTR as described by FORM. +@@ -1192,6 +1207,9 @@ read_attribute_value (struct attribute * attr, + + switch (form) + { ++ case DW_FORM_flag_present: ++ attr->u.val = 1; ++ break; + case DW_FORM_ref_addr: + /* DW_FORM_ref_addr is an address in DWARF2, and an offset in + DWARF3. */ +@@ -1237,15 +1255,32 @@ read_attribute_value (struct attribute * attr, + info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk); + attr->u.blk = blk; + break; ++ case DW_FORM_ref1: ++ case DW_FORM_flag: ++ case DW_FORM_data1: ++ case DW_FORM_addrx1: ++ attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end); ++ info_ptr += 1; ++ break; + case DW_FORM_data2: ++ case DW_FORM_ref2: + attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end); + info_ptr += 2; + break; ++ case DW_FORM_addrx3: ++ attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end); ++ attr->u.val &= 0xffffff; ++ info_ptr += 3; ++ break; ++ case DW_FORM_ref4: + case DW_FORM_data4: ++ case DW_FORM_addrx4: + attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end); + info_ptr += 4; + break; + case DW_FORM_data8: ++ case DW_FORM_ref8: ++ case DW_FORM_ref_sig8: + attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end); + info_ptr += 8; + break; +@@ -1265,6 +1300,33 @@ read_attribute_value (struct attribute * attr, + attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read); + info_ptr += bytes_read; + break; ++ case DW_FORM_strx1: ++ attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end); ++ info_ptr += 1; ++ attr->u.str = (char *) read_indexed_string (attr->u.val, unit); ++ break; ++ case DW_FORM_strx2: ++ attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end); ++ info_ptr += 2; ++ attr->u.str = (char *) read_indexed_string (attr->u.val, unit); ++ break; ++ case DW_FORM_strx3: ++ attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end); ++ info_ptr += 3; ++ attr->u.val &= 0xffffff; ++ attr->u.str = (char *) read_indexed_string (attr->u.val, unit); ++ break; ++ case DW_FORM_strx4: ++ attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end); ++ info_ptr += 4; ++ attr->u.str = (char *) read_indexed_string (attr->u.val, unit); ++ break; ++ case DW_FORM_strx: ++ attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, ++ FALSE, info_ptr_end); ++ info_ptr += bytes_read; ++ attr->u.str = (char *) read_indexed_string (attr->u.val, unit); ++ break; + case DW_FORM_exprloc: + case DW_FORM_block: + amt = sizeof (struct dwarf_block); +@@ -1287,48 +1349,14 @@ read_attribute_value (struct attribute * attr, + info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk); + attr->u.blk = blk; + break; +- case DW_FORM_data1: +- attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end); +- info_ptr += 1; +- break; +- case DW_FORM_flag: +- attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end); +- info_ptr += 1; +- break; +- case DW_FORM_flag_present: +- attr->u.val = 1; +- break; + case DW_FORM_sdata: + attr->u.sval = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, + TRUE, info_ptr_end); + info_ptr += bytes_read; + break; +- case DW_FORM_udata: +- attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, +- FALSE, info_ptr_end); +- info_ptr += bytes_read; +- break; +- case DW_FORM_ref1: +- attr->u.val = read_1_byte (abfd, info_ptr, info_ptr_end); +- info_ptr += 1; +- break; +- case DW_FORM_ref2: +- attr->u.val = read_2_bytes (abfd, info_ptr, info_ptr_end); +- info_ptr += 2; +- break; +- case DW_FORM_ref4: +- attr->u.val = read_4_bytes (abfd, info_ptr, info_ptr_end); +- info_ptr += 4; +- break; +- case DW_FORM_ref8: +- attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end); +- info_ptr += 8; +- break; +- case DW_FORM_ref_sig8: +- attr->u.val = read_8_bytes (abfd, info_ptr, info_ptr_end); +- info_ptr += 8; +- break; + case DW_FORM_ref_udata: ++ case DW_FORM_udata: ++ case DW_FORM_addrx: + attr->u.val = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, + FALSE, info_ptr_end); + info_ptr += bytes_read; +@@ -1361,6 +1389,7 @@ read_attribute_value (struct attribute * attr, + info_ptr = read_n_bytes (info_ptr, info_ptr_end, blk); + attr->u.blk = blk; + break; ++ + default: + _bfd_error_handler (_("DWARF error: invalid or unhandled FORM value: %#x"), + form); diff --git a/poky/meta/recipes-devtools/binutils/binutils/0018-Add-DWARF-5-support-in-gold.patch b/poky/meta/recipes-devtools/binutils/binutils/0018-Add-DWARF-5-support-in-gold.patch new file mode 100644 index 000000000..353b68085 --- /dev/null +++ b/poky/meta/recipes-devtools/binutils/binutils/0018-Add-DWARF-5-support-in-gold.patch @@ -0,0 +1,1374 @@ +From 29dab7648672342418a9d32767e3b3182d9e6a30 Mon Sep 17 00:00:00 2001 +From: Cary Coutant <ccoutant@gmail.com> +Date: Wed, 17 Mar 2021 21:31:15 -0700 +Subject: [PATCH] Add DWARF 5 support in gold. + +elfcpp/ + PR gold/27246 + * dwarf.h (enum DW_LNCT): Add line number table content type codes. + (enum DW_LINE_OPS): Reformat. + (enum DW_LINE_EXTENDED_OPS): Reformat. + (enum DW_CHILDREN): Reformat. + (enum DW_RLE): Add range list entry types. + (enum DW_SECT): Update values for DWARF 5. + +gold/ + PR gold/27246 + * dwarf_reader.cc (Dwarf_abbrev_table::do_get_abbrev): Handle + DW_FORM_implicit_const. + (Dwarf_ranges_table::read_ranges_table): Add version parameter; + Adjust all callers. Look for .debug_rnglists section if DWARF 5. + (Dwarf_ranges_table::read_range_list_v5): New method. + (Dwarf_die::read_attributes): Handle new DWARF 5 DW_FORM codes. + (Dwarf_die::skip_attributes): Likewise. + (Dwarf_info_reader::do_parse): Support DWARF 5 unit header format. + (Dwarf_info_reader::read_3bytes_from_pointer): New method. + (Sized_dwarf_line_info::Sized_dwarf_line_info): Initialize + str_buffer_, str_buffer_start, reloc_map_, line_number_map_. + Look for .debug_line_str section. + (Sized_dwarf_line_info::read_header_prolog): Support DWARF 5 prolog. + (Sized_dwarf_line_info::read_header_tables): Rename to... + (Sized_dwarf_line_info::read_header_tables_v2): ... this. + (Sized_dwarf_line_info::read_header_tables_v5): New method. + (Sized_dwarf_line_info::process_one_opcode): Insert missing "this->". + Change advance_line to signed int64_t. + (Sized_dwarf_line_info::read_lines): Add endptr parameter; adjust + callers. Insert missing "this->". + (Sized_dwarf_line_info::read_line_mappings): Support DWARF 5. + (Sized_dwarf_line_info::do_addr2line): Add debug code. + * dwarf_reader.h (Dwarf_abbrev_table::Attribute): Add implicit_const + field. Adjust constructor. + (Dwarf_abbrev_table::add_sttribute): Add implicit_const parameter. + (Dwarf_ranges_table::read_ranges_table): Add version parameter. + (Dwarf_ranges_table::read_range_list_v5): New method. + (Dwarf_die): Remove unused attr_off field. + (Dwarf_info_reader::Dwarf_info_reader): Initialize unit_type_ field. + (Dwarf_info_reader::is_type_unit): New method. + (Dwarf_info_reader::read_3bytes_from_pointer): New method. + (Dwarf_info_reader::read_range_list): Call read_range_list_v5 for + DWARF 5 range lists. + (Dwarf_info_reader::is_type_unit_): Remove. + (Dwarf_info_reader::unit_type_): New field. + (Sized_dwarf_line_info::~Sized_dwarf_line_info): Delete + str_buffer_start_. + (Sized_dwarf_line_info::read_header_tables): Rename to... + (Sized_dwarf_line_info::read_header_tables_v2): ... this. + (Sized_dwarf_line_info::read_header_tables_v5): New method. + (Sized_dwarf_line_info::read_lines): Add endptr parameter. + (Sized_dwarf_line_info::Dwarf_line_infoHeader): Add address_size field. + (Sized_dwarf_line_info::str_buffer_): New field. + (Sized_dwarf_line_info::str_buffer_end_): New field. + (Sized_dwarf_line_info::str_buffer_start_): New field. + (Sized_dwarf_line_info::end_of_header_length_): New field. + (Sized_dwarf_line_info::end_of_unit_): New field. + +Upstream-Status: Backport [5cde809b7b9 Add DWARF 5 support in gold.] + +Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> +--- + elfcpp/dwarf.h | 89 +++++-- + gold/dwarf_reader.cc | 591 +++++++++++++++++++++++++++++++++++++------ + gold/dwarf_reader.h | 103 ++++++-- + 3 files changed, 654 insertions(+), 129 deletions(-) + +diff --git a/elfcpp/dwarf.h b/elfcpp/dwarf.h +index e24347f8481..c9a9e02369c 100644 +--- a/elfcpp/dwarf.h ++++ b/elfcpp/dwarf.h +@@ -152,35 +152,48 @@ enum DW_EH_PE + DW_EH_PE_indirect = 0x80 + }; + ++// Line number table content type codes. ++ ++enum DW_LNCT ++{ ++ DW_LNCT_path = 0x1, ++ DW_LNCT_directory_index = 0x2, ++ DW_LNCT_timestamp = 0x3, ++ DW_LNCT_size = 0x4, ++ DW_LNCT_MD5 = 0x5, ++ DW_LNCT_lo_user = 0x2000, ++ DW_LNCT_hi_user = 0x3fff ++}; ++ + // Line number opcodes. + + enum DW_LINE_OPS + { +- DW_LNS_extended_op = 0, +- DW_LNS_copy = 1, +- DW_LNS_advance_pc = 2, +- DW_LNS_advance_line = 3, +- DW_LNS_set_file = 4, +- DW_LNS_set_column = 5, +- DW_LNS_negate_stmt = 6, +- DW_LNS_set_basic_block = 7, +- DW_LNS_const_add_pc = 8, +- DW_LNS_fixed_advance_pc = 9, ++ DW_LNS_extended_op = 0x00, ++ DW_LNS_copy = 0x01, ++ DW_LNS_advance_pc = 0x02, ++ DW_LNS_advance_line = 0x03, ++ DW_LNS_set_file = 0x04, ++ DW_LNS_set_column = 0x05, ++ DW_LNS_negate_stmt = 0x06, ++ DW_LNS_set_basic_block = 0x07, ++ DW_LNS_const_add_pc = 0x08, ++ DW_LNS_fixed_advance_pc = 0x09, + // DWARF 3. +- DW_LNS_set_prologue_end = 10, +- DW_LNS_set_epilogue_begin = 11, +- DW_LNS_set_isa = 12 ++ DW_LNS_set_prologue_end = 0x0a, ++ DW_LNS_set_epilogue_begin = 0x0b, ++ DW_LNS_set_isa = 0x0c + }; + + // Line number extended opcodes. + + enum DW_LINE_EXTENDED_OPS + { +- DW_LNE_end_sequence = 1, +- DW_LNE_set_address = 2, +- DW_LNE_define_file = 3, ++ DW_LNE_end_sequence = 0x01, ++ DW_LNE_set_address = 0x02, ++ DW_LNE_define_file = 0x03, + // DWARF4. +- DW_LNE_set_discriminator = 4, ++ DW_LNE_set_discriminator = 0x04, + // HP extensions. + DW_LNE_HP_negate_is_UV_update = 0x11, + DW_LNE_HP_push_context = 0x12, +@@ -191,13 +204,15 @@ enum DW_LINE_EXTENDED_OPS + DW_LNE_HP_negate_post_semantics = 0x17, + DW_LNE_HP_negate_function_exit = 0x18, + DW_LNE_HP_negate_front_end_logical = 0x19, +- DW_LNE_HP_define_proc = 0x20 ++ DW_LNE_HP_define_proc = 0x20, ++ DW_LNE_lo_user = 0x80, ++ DW_LNE_hi_user = 0xff + }; + + enum DW_CHILDREN + { +- DW_CHILDREN_no =0x00, +- DW_CHILDREN_yes =0x01 ++ DW_CHILDREN_no = 0, ++ DW_CHILDREN_yes = 1 + }; + + // Source language names and codes. +@@ -247,20 +262,38 @@ enum DW_LANG + DW_LANG_HP_Assembler = 0x8007 + }; + ++// Range list entry kinds in .debug_rnglists* section. ++ ++enum DW_RLE ++{ ++ DW_RLE_end_of_list = 0x00, ++ DW_RLE_base_addressx = 0x01, ++ DW_RLE_startx_endx = 0x02, ++ DW_RLE_startx_length = 0x03, ++ DW_RLE_offset_pair = 0x04, ++ DW_RLE_base_address = 0x05, ++ DW_RLE_start_end = 0x06, ++ DW_RLE_start_length = 0x07 ++}; ++ + // DWARF section identifiers used in the package format. + // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFissionDWP. ++// Added (with changes) in DWARF 5. + + enum DW_SECT + { +- DW_SECT_INFO = 1, +- DW_SECT_TYPES = 2, +- DW_SECT_ABBREV = 3, +- DW_SECT_LINE = 4, +- DW_SECT_LOC = 5, ++ DW_SECT_INFO = 1, ++ DW_SECT_ABBREV = 3, ++ DW_SECT_LINE = 4, ++ DW_SECT_LOCLISTS = 5, + DW_SECT_STR_OFFSETS = 6, +- DW_SECT_MACINFO = 7, +- DW_SECT_MACRO = 8, +- DW_SECT_MAX = DW_SECT_MACRO, ++ DW_SECT_MACINFO = 7, ++ DW_SECT_RNGLISTS = 8, ++ DW_SECT_MAX = DW_SECT_RNGLISTS, ++ // These were used only for the experimental Fission support in DWARF 4. ++ DW_SECT_TYPES = 2, ++ DW_SECT_LOC = 5, ++ DW_SECT_MACRO = 8 + }; + + } // End namespace elfcpp. +diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc +index f0e6b89bde2..83a0114ed39 100644 +--- a/gold/dwarf_reader.cc ++++ b/gold/dwarf_reader.cc +@@ -26,6 +26,7 @@ + #include <utility> + #include <vector> + ++#include "debug.h" + #include "elfcpp_swap.h" + #include "dwarf.h" + #include "object.h" +@@ -275,6 +276,14 @@ Dwarf_abbrev_table::do_get_abbrev(unsigned int code) + uint64_t form = read_unsigned_LEB_128(this->buffer_pos_, &len); + this->buffer_pos_ += len; + ++ // For DW_FORM_implicit_const, read the constant. ++ int64_t implicit_const = 0; ++ if (form == elfcpp::DW_FORM_implicit_const) ++ { ++ implicit_const = read_signed_LEB_128(this->buffer_pos_, &len); ++ this->buffer_pos_ += len; ++ } ++ + // A (0,0) pair terminates the list. + if (attr == 0 && form == 0) + break; +@@ -282,7 +291,7 @@ Dwarf_abbrev_table::do_get_abbrev(unsigned int code) + if (attr == elfcpp::DW_AT_sibling) + entry->has_sibling_attribute = true; + +- entry->add_attribute(attr, form); ++ entry->add_attribute(attr, form, implicit_const); + } + + this->store_abbrev(nextcode, entry); +@@ -302,8 +311,16 @@ Dwarf_ranges_table::read_ranges_table( + Relobj* object, + const unsigned char* symtab, + off_t symtab_size, +- unsigned int ranges_shndx) ++ unsigned int ranges_shndx, ++ unsigned int version) + { ++ const std::string section_name(version < 5 ++ ? ".debug_ranges" ++ : ".debug_rnglists"); ++ const std::string compressed_section_name(version < 5 ++ ? ".zdebug_ranges" ++ : ".zdebug_rnglists"); ++ + // If we've already read this abbrev table, return immediately. + if (this->ranges_shndx_ > 0 + && this->ranges_shndx_ == ranges_shndx) +@@ -318,7 +335,7 @@ Dwarf_ranges_table::read_ranges_table( + for (unsigned int i = 1; i < object->shnum(); ++i) + { + std::string name = object->section_name(i); +- if (name == ".debug_ranges" || name == ".zdebug_ranges") ++ if (name == section_name || name == compressed_section_name) + { + ranges_shndx = i; + this->output_section_offset_ = object->output_section_offset(i); +@@ -393,7 +410,7 @@ Dwarf_ranges_table::read_range_list( + { + Dwarf_range_list* ranges; + +- if (!this->read_ranges_table(object, symtab, symtab_size, ranges_shndx)) ++ if (!this->read_ranges_table(object, symtab, symtab_size, ranges_shndx, 4)) + return NULL; + + // Correct the offset. For incremental update links, we have a +@@ -459,6 +476,125 @@ Dwarf_ranges_table::read_range_list( + return ranges; + } + ++// Read a DWARF 5 range list from section RANGES_SHNDX at offset RANGES_OFFSET. ++ ++Dwarf_range_list* ++Dwarf_ranges_table::read_range_list_v5( ++ Relobj* object, ++ const unsigned char* symtab, ++ off_t symtab_size, ++ unsigned int addr_size, ++ unsigned int ranges_shndx, ++ off_t offset) ++{ ++ Dwarf_range_list* ranges; ++ ++ if (!this->read_ranges_table(object, symtab, symtab_size, ranges_shndx, 5)) ++ return NULL; ++ ++ ranges = new Dwarf_range_list(); ++ off_t base = 0; ++ unsigned int shndx0 = 0; ++ ++ // Correct the offset. For incremental update links, we have a ++ // relocated offset that is relative to the output section, but ++ // here we need an offset relative to the input section. ++ offset -= this->output_section_offset_; ++ ++ // Read the range list at OFFSET. ++ const unsigned char* prle = this->ranges_buffer_ + offset; ++ while (prle < this->ranges_buffer_end_) ++ { ++ off_t start; ++ off_t end; ++ unsigned int shndx1 = 0; ++ unsigned int shndx2 = 0; ++ size_t len; ++ ++ // Read the entry type. ++ unsigned int rle_type = *prle++; ++ offset += 1; ++ ++ if (rle_type == elfcpp::DW_RLE_end_of_list) ++ break; ++ ++ switch (rle_type) ++ { ++ case elfcpp::DW_RLE_base_address: ++ if (addr_size == 4) ++ base = this->dwinfo_->read_from_pointer<32>(prle); ++ else ++ base = this->dwinfo_->read_from_pointer<64>(prle); ++ if (this->ranges_reloc_mapper_ != NULL) ++ shndx0 = this->lookup_reloc(offset, &base); ++ prle += addr_size; ++ offset += addr_size; ++ break; ++ ++ case elfcpp::DW_RLE_offset_pair: ++ start = read_unsigned_LEB_128(prle, &len); ++ prle += len; ++ offset += len; ++ end = read_unsigned_LEB_128(prle, &len); ++ prle += len; ++ offset += len; ++ if (shndx0 == 0 || object->is_section_included(shndx0)) ++ ranges->add(shndx0, base + start, base + end); ++ break; ++ ++ case elfcpp::DW_RLE_start_end: ++ if (addr_size == 4) ++ { ++ start = this->dwinfo_->read_from_pointer<32>(prle); ++ end = this->dwinfo_->read_from_pointer<32>(prle + 4); ++ } ++ else ++ { ++ start = this->dwinfo_->read_from_pointer<64>(prle); ++ end = this->dwinfo_->read_from_pointer<64>(prle + 8); ++ } ++ if (this->ranges_reloc_mapper_ != NULL) ++ { ++ shndx1 = this->lookup_reloc(offset, &start); ++ shndx2 = this->lookup_reloc(offset + addr_size, &end); ++ if (shndx1 != shndx2) ++ gold_warning(_("%s: DWARF info may be corrupt; offsets in a " ++ "range list entry are in different sections"), ++ object->name().c_str()); ++ } ++ prle += addr_size * 2; ++ offset += addr_size * 2; ++ if (shndx1 == 0 || object->is_section_included(shndx1)) ++ ranges->add(shndx1, start, end); ++ break; ++ ++ case elfcpp::DW_RLE_start_length: ++ if (addr_size == 4) ++ start = this->dwinfo_->read_from_pointer<32>(prle); ++ else ++ start = this->dwinfo_->read_from_pointer<64>(prle); ++ if (this->ranges_reloc_mapper_ != NULL) ++ shndx1 = this->lookup_reloc(offset, &start); ++ prle += addr_size; ++ offset += addr_size; ++ end = start + read_unsigned_LEB_128(prle, &len); ++ prle += len; ++ offset += len; ++ if (shndx1 == 0 || object->is_section_included(shndx1)) ++ ranges->add(shndx1, start, end); ++ break; ++ ++ default: ++ gold_warning(_("%s: DWARF range list contains " ++ "unsupported entry type (%d)"), ++ object->name().c_str(), rle_type); ++ break; ++ } ++ } ++ ++ return ranges; ++} ++ + // Look for a relocation at offset OFF in the range table, + // and return the section index and offset of the target. + +@@ -709,7 +845,13 @@ Dwarf_die::read_attributes() + case elfcpp::DW_FORM_flag_present: + attr_value.val.intval = 1; + break; ++ case elfcpp::DW_FORM_implicit_const: ++ attr_value.val.intval = ++ this->abbrev_code_->attributes[i].implicit_const; ++ break; + case elfcpp::DW_FORM_strp: ++ case elfcpp::DW_FORM_strp_sup: ++ case elfcpp::DW_FORM_line_strp: + { + off_t str_off; + if (this->dwinfo_->offset_size() == 4) +@@ -722,6 +864,26 @@ Dwarf_die::read_attributes() + attr_value.val.refval = str_off; + break; + } ++ case elfcpp::DW_FORM_strx: ++ case elfcpp::DW_FORM_GNU_str_index: ++ attr_value.val.uintval = read_unsigned_LEB_128(pattr, &len); ++ pattr += len; ++ break; ++ case elfcpp::DW_FORM_strx1: ++ attr_value.val.uintval = *pattr++; ++ break; ++ case elfcpp::DW_FORM_strx2: ++ attr_value.val.uintval = ++ this->dwinfo_->read_from_pointer<16>(&pattr); ++ break; ++ case elfcpp::DW_FORM_strx3: ++ attr_value.val.uintval = ++ this->dwinfo_->read_3bytes_from_pointer(&pattr); ++ break; ++ case elfcpp::DW_FORM_strx4: ++ attr_value.val.uintval = ++ this->dwinfo_->read_from_pointer<32>(&pattr); ++ break; + case elfcpp::DW_FORM_sec_offset: + { + off_t sec_off; +@@ -747,7 +909,6 @@ Dwarf_die::read_attributes() + this->dwinfo_->lookup_reloc(attr_off, &sec_off); + attr_value.aux.shndx = shndx; + attr_value.val.refval = sec_off; +- ref_form = true; + break; + } + case elfcpp::DW_FORM_ref_addr: +@@ -815,6 +976,7 @@ Dwarf_die::read_attributes() + break; + } + case elfcpp::DW_FORM_ref4: ++ case elfcpp::DW_FORM_ref_sup4: + { + off_t sec_off; + sec_off = this->dwinfo_->read_from_pointer<32>(&pattr); +@@ -835,11 +997,20 @@ Dwarf_die::read_attributes() + attr_value.val.intval = sec_off; + break; + } ++ case elfcpp::DW_FORM_data16: ++ { ++ // For now, treat this as a 16-byte block. ++ attr_value.val.blockval = pattr; ++ attr_value.aux.blocklen = 16; ++ pattr += 16; ++ break; ++ } + case elfcpp::DW_FORM_ref_sig8: + attr_value.val.uintval = + this->dwinfo_->read_from_pointer<64>(&pattr); + break; + case elfcpp::DW_FORM_ref8: ++ case elfcpp::DW_FORM_ref_sup8: + { + off_t sec_off; + sec_off = this->dwinfo_->read_from_pointer<64>(&pattr); +@@ -856,11 +1027,29 @@ Dwarf_die::read_attributes() + pattr += len; + break; + case elfcpp::DW_FORM_udata: ++ attr_value.val.uintval = read_unsigned_LEB_128(pattr, &len); ++ pattr += len; ++ break; ++ case elfcpp::DW_FORM_addrx: + case elfcpp::DW_FORM_GNU_addr_index: +- case elfcpp::DW_FORM_GNU_str_index: + attr_value.val.uintval = read_unsigned_LEB_128(pattr, &len); + pattr += len; + break; ++ case elfcpp::DW_FORM_addrx1: ++ attr_value.val.uintval = *pattr++; ++ break; ++ case elfcpp::DW_FORM_addrx2: ++ attr_value.val.uintval = ++ this->dwinfo_->read_from_pointer<16>(&pattr); ++ break; ++ case elfcpp::DW_FORM_addrx3: ++ attr_value.val.uintval = ++ this->dwinfo_->read_3bytes_from_pointer(&pattr); ++ break; ++ case elfcpp::DW_FORM_addrx4: ++ attr_value.val.uintval = ++ this->dwinfo_->read_from_pointer<32>(&pattr); ++ break; + case elfcpp::DW_FORM_sdata: + attr_value.val.intval = read_signed_LEB_128(pattr, &len); + pattr += len; +@@ -870,6 +1059,11 @@ Dwarf_die::read_attributes() + len = strlen(attr_value.val.stringval); + pattr += len + 1; + break; ++ case elfcpp::DW_FORM_loclistx: ++ case elfcpp::DW_FORM_rnglistx: ++ attr_value.val.uintval = read_unsigned_LEB_128(pattr, &len); ++ pattr += len; ++ break; + default: + return false; + } +@@ -954,9 +1148,12 @@ Dwarf_die::skip_attributes() + switch(form) + { + case elfcpp::DW_FORM_flag_present: ++ case elfcpp::DW_FORM_implicit_const: + break; + case elfcpp::DW_FORM_strp: + case elfcpp::DW_FORM_sec_offset: ++ case elfcpp::DW_FORM_strp_sup: ++ case elfcpp::DW_FORM_line_strp: + pattr += this->dwinfo_->offset_size(); + break; + case elfcpp::DW_FORM_addr: +@@ -993,23 +1190,42 @@ Dwarf_die::skip_attributes() + case elfcpp::DW_FORM_data1: + case elfcpp::DW_FORM_ref1: + case elfcpp::DW_FORM_flag: ++ case elfcpp::DW_FORM_strx1: ++ case elfcpp::DW_FORM_addrx1: + pattr += 1; + break; + case elfcpp::DW_FORM_data2: + case elfcpp::DW_FORM_ref2: ++ case elfcpp::DW_FORM_strx2: ++ case elfcpp::DW_FORM_addrx2: + pattr += 2; + break; ++ case elfcpp::DW_FORM_strx3: ++ case elfcpp::DW_FORM_addrx3: ++ pattr += 3; ++ break; + case elfcpp::DW_FORM_data4: + case elfcpp::DW_FORM_ref4: ++ case elfcpp::DW_FORM_ref_sup4: ++ case elfcpp::DW_FORM_strx4: ++ case elfcpp::DW_FORM_addrx4: + pattr += 4; + break; + case elfcpp::DW_FORM_data8: + case elfcpp::DW_FORM_ref8: + case elfcpp::DW_FORM_ref_sig8: ++ case elfcpp::DW_FORM_ref_sup8: + pattr += 8; + break; ++ case elfcpp::DW_FORM_data16: ++ pattr += 16; ++ break; + case elfcpp::DW_FORM_ref_udata: + case elfcpp::DW_FORM_udata: ++ case elfcpp::DW_FORM_addrx: ++ case elfcpp::DW_FORM_strx: ++ case elfcpp::DW_FORM_loclistx: ++ case elfcpp::DW_FORM_rnglistx: + case elfcpp::DW_FORM_GNU_addr_index: + case elfcpp::DW_FORM_GNU_str_index: + read_unsigned_LEB_128(pattr, &len); +@@ -1313,6 +1529,13 @@ Dwarf_info_reader::do_parse() + elfcpp::Swap_unaligned<16, big_endian>::readval(pinfo); + pinfo += 2; + ++ // DWARF 5: Read the unit type (1 byte) and address size (1 byte). ++ if (this->cu_version_ >= 5) ++ { ++ this->unit_type_ = *pinfo++; ++ this->address_size_ = *pinfo++; ++ } ++ + // Read debug_abbrev_offset (4 or 8 bytes). + if (this->offset_size_ == 4) + abbrev_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(pinfo); +@@ -1333,13 +1556,14 @@ Dwarf_info_reader::do_parse() + } + pinfo += this->offset_size_; + +- // Read address_size (1 byte). +- this->address_size_ = *pinfo++; ++ // DWARF 2-4: Read address_size (1 byte). ++ if (this->cu_version_ < 5) ++ this->address_size_ = *pinfo++; + + // For type units, read the two extra fields. + uint64_t signature = 0; + off_t type_offset = 0; +- if (this->is_type_unit_) ++ if (this->is_type_unit()) + { + if (!this->check_buffer(pinfo + 8 + this->offset_size_)) + break; +@@ -1369,7 +1593,7 @@ Dwarf_info_reader::do_parse() + if (root_die.tag() != 0) + { + // Visit the CU or TU. +- if (this->is_type_unit_) ++ if (this->is_type_unit()) + this->visit_type_unit(section_offset + this->cu_offset_, + cu_end - cu_start, type_offset, signature, + &root_die); +@@ -1460,6 +1684,19 @@ Dwarf_info_reader::read_from_pointer(const unsigned char** source) + return return_value; + } + ++// Read a 3-byte integer. Update SOURCE after read. ++inline typename elfcpp::Valtype_base<32>::Valtype ++Dwarf_info_reader::read_3bytes_from_pointer(const unsigned char** source) ++{ ++ typename elfcpp::Valtype_base<32>::Valtype return_value; ++ if (this->object_->is_big_endian()) ++ return_value = ((*source)[0] << 16) | ((*source)[1] << 8) | (*source)[2]; ++ else ++ return_value = ((*source)[2] << 16) | ((*source)[1] << 8) | (*source)[0]; ++ *source += 3; ++ return return_value; ++} ++ + // Look for a relocation at offset ATTR_OFF in the dwarf info, + // and return the section index and offset of the target. + +@@ -1561,27 +1798,40 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info( + Object* object, + unsigned int read_shndx) + : data_valid_(false), buffer_(NULL), buffer_start_(NULL), ++ str_buffer_(NULL), str_buffer_start_(NULL), + reloc_mapper_(NULL), symtab_buffer_(NULL), directories_(), files_(), +- current_header_index_(-1) ++ current_header_index_(-1), reloc_map_(), line_number_map_() + { +- unsigned int debug_shndx; ++ unsigned int debug_line_shndx = 0; ++ unsigned int debug_line_str_shndx = 0; + +- for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx) ++ for (unsigned int i = 1; i < object->shnum(); ++i) + { ++ section_size_type buffer_size; ++ bool is_new = false; ++ + // FIXME: do this more efficiently: section_name() isn't super-fast +- std::string name = object->section_name(debug_shndx); ++ std::string name = object->section_name(i); + if (name == ".debug_line" || name == ".zdebug_line") + { +- section_size_type buffer_size; +- bool is_new = false; +- this->buffer_ = object->decompressed_section_contents(debug_shndx, +- &buffer_size, +- &is_new); ++ this->buffer_ = ++ object->decompressed_section_contents(i, &buffer_size, &is_new); + if (is_new) + this->buffer_start_ = this->buffer_; + this->buffer_end_ = this->buffer_ + buffer_size; +- break; ++ debug_line_shndx = i; ++ } ++ else if (name == ".debug_line_str" || name == ".zdebug_line_str") ++ { ++ this->str_buffer_ = ++ object->decompressed_section_contents(i, &buffer_size, &is_new); ++ if (is_new) ++ this->str_buffer_start_ = this->str_buffer_; ++ this->str_buffer_end_ = this->str_buffer_ + buffer_size; ++ debug_line_str_shndx = i; + } ++ if (debug_line_shndx > 0 && debug_line_str_shndx > 0) ++ break; + } + if (this->buffer_ == NULL) + return; +@@ -1594,7 +1844,7 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info( + unsigned int reloc_sh_type = object->section_type(i); + if ((reloc_sh_type == elfcpp::SHT_REL + || reloc_sh_type == elfcpp::SHT_RELA) +- && object->section_info(i) == debug_shndx) ++ && object->section_info(i) == debug_line_shndx) + { + reloc_shndx = i; + this->track_relocs_type_ = reloc_sh_type; +@@ -1640,65 +1890,80 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog( + uint32_t initial_length = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr); + lineptr += 4; + +- // In DWARF2/3, if the initial length is all 1 bits, then the offset ++ // In DWARF, if the initial length is all 1 bits, then the offset + // size is 8 and we need to read the next 8 bytes for the real length. + if (initial_length == 0xffffffff) + { +- header_.offset_size = 8; ++ this->header_.offset_size = 8; + initial_length = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr); + lineptr += 8; + } + else +- header_.offset_size = 4; ++ this->header_.offset_size = 4; + +- header_.total_length = initial_length; ++ this->header_.total_length = initial_length; + +- gold_assert(lineptr + header_.total_length <= buffer_end_); ++ this->end_of_unit_ = lineptr + initial_length; ++ gold_assert(this->end_of_unit_ <= buffer_end_); + +- header_.version = elfcpp::Swap_unaligned<16, big_endian>::readval(lineptr); ++ this->header_.version = ++ elfcpp::Swap_unaligned<16, big_endian>::readval(lineptr); + lineptr += 2; + +- // Skip address size and segment selector for DWARF5. +- if (header_.version >= 5) +- lineptr += 2; ++ // We can only read versions 2-5 of the DWARF line number table. ++ // For other versions, just skip the entire line number table. ++ if (this->header_.version < 2 || this->header_.version > 5) ++ return this->end_of_unit_; + +- if (header_.offset_size == 4) +- header_.prologue_length = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr); ++ // DWARF 5 only: address size and segment selector. ++ if (this->header_.version >= 5) ++ { ++ this->header_.address_size = *lineptr; ++ // We ignore the segment selector. ++ lineptr += 2; ++ } ++ ++ if (this->header_.offset_size == 4) ++ this->header_.prologue_length = ++ elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr); + else +- header_.prologue_length = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr); +- lineptr += header_.offset_size; ++ this->header_.prologue_length = ++ elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr); ++ lineptr += this->header_.offset_size; + +- header_.min_insn_length = *lineptr; ++ this->end_of_header_length_ = lineptr; ++ ++ this->header_.min_insn_length = *lineptr; + lineptr += 1; + +- if (header_.version < 4) +- header_.max_ops_per_insn = 1; ++ if (this->header_.version < 4) ++ this->header_.max_ops_per_insn = 1; + else + { + // DWARF 4 added the maximum_operations_per_instruction field. +- header_.max_ops_per_insn = *lineptr; ++ this->header_.max_ops_per_insn = *lineptr; + lineptr += 1; + // TODO: Add support for values other than 1. +- gold_assert(header_.max_ops_per_insn == 1); ++ gold_assert(this->header_.max_ops_per_insn == 1); + } + +- header_.default_is_stmt = *lineptr; ++ this->header_.default_is_stmt = *lineptr; + lineptr += 1; + +- header_.line_base = *reinterpret_cast<const signed char*>(lineptr); ++ this->header_.line_base = *reinterpret_cast<const signed char*>(lineptr); + lineptr += 1; + +- header_.line_range = *lineptr; ++ this->header_.line_range = *lineptr; + lineptr += 1; + +- header_.opcode_base = *lineptr; ++ this->header_.opcode_base = *lineptr; + lineptr += 1; + +- header_.std_opcode_lengths.resize(header_.opcode_base + 1); +- header_.std_opcode_lengths[0] = 0; +- for (int i = 1; i < header_.opcode_base; i++) ++ this->header_.std_opcode_lengths.resize(this->header_.opcode_base + 1); ++ this->header_.std_opcode_lengths[0] = 0; ++ for (int i = 1; i < this->header_.opcode_base; i++) + { +- header_.std_opcode_lengths[i] = *lineptr; ++ this->header_.std_opcode_lengths[i] = *lineptr; + lineptr += 1; + } + +@@ -1707,10 +1972,11 @@ Sized_dwarf_line_info<size, big_endian>::read_header_prolog( + + // The header for a debug_line section is mildly complicated, because + // the line info is very tightly encoded. ++// This routine is for DWARF versions 2, 3, and 4. + + template<int size, bool big_endian> + const unsigned char* +-Sized_dwarf_line_info<size, big_endian>::read_header_tables( ++Sized_dwarf_line_info<size, big_endian>::read_header_tables_v2( + const unsigned char* lineptr) + { + ++this->current_header_index_; +@@ -1775,6 +2041,169 @@ Sized_dwarf_line_info<size, big_endian>::read_header_tables( + return lineptr; + } + ++// This routine is for DWARF version 5. ++ ++template<int size, bool big_endian> ++const unsigned char* ++Sized_dwarf_line_info<size, big_endian>::read_header_tables_v5( ++ const unsigned char* lineptr) ++{ ++ size_t len; ++ ++ ++this->current_header_index_; ++ ++ gold_assert(static_cast<int>(this->directories_.size()) ++ == this->current_header_index_); ++ gold_assert(static_cast<int>(this->files_.size()) ++ == this->current_header_index_); ++ ++ // Read the directory list. ++ unsigned int format_count = *lineptr; ++ lineptr += 1; ++ ++ unsigned int *types = new unsigned int[format_count]; ++ unsigned int *forms = new unsigned int[format_count]; ++ ++ for (unsigned int i = 0; i < format_count; i++) ++ { ++ types[i] = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ forms[i] = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ } ++ ++ uint64_t entry_count = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ this->directories_.push_back(std::vector<std::string>(0)); ++ std::vector<std::string>& dir_list = this->directories_.back(); ++ ++ for (unsigned int j = 0; j < entry_count; j++) ++ { ++ std::string dirname; ++ ++ for (unsigned int i = 0; i < format_count; i++) ++ { ++ if (types[i] == elfcpp::DW_LNCT_path) ++ { ++ if (forms[i] == elfcpp::DW_FORM_string) ++ { ++ dirname = reinterpret_cast<const char*>(lineptr); ++ lineptr += dirname.size() + 1; ++ } ++ else if (forms[i] == elfcpp::DW_FORM_line_strp) ++ { ++ uint64_t offset; ++ if (this->header_.offset_size == 4) ++ offset = ++ elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr); ++ else ++ offset = ++ elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr); ++ typename Reloc_map::const_iterator it ++ = this->reloc_map_.find(lineptr - this->buffer_); ++ if (it != reloc_map_.end()) ++ { ++ if (this->track_relocs_type_ == elfcpp::SHT_RELA) ++ offset = 0; ++ offset += it->second.second; ++ } ++ lineptr += this->header_.offset_size; ++ dirname = reinterpret_cast<const char*>(this->str_buffer_ ++ + offset); ++ } ++ else ++ return lineptr; ++ } ++ else ++ return lineptr; ++ } ++ dir_list.push_back(dirname); ++ } ++ ++ delete[] types; ++ delete[] forms; ++ ++ // Read the filenames list. ++ format_count = *lineptr; ++ lineptr += 1; ++ ++ types = new unsigned int[format_count]; ++ forms = new unsigned int[format_count]; ++ ++ for (unsigned int i = 0; i < format_count; i++) ++ { ++ types[i] = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ forms[i] = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ } ++ ++ entry_count = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ this->files_.push_back( ++ std::vector<std::pair<int, std::string> >(0)); ++ std::vector<std::pair<int, std::string> >& file_list = this->files_.back(); ++ ++ for (unsigned int j = 0; j < entry_count; j++) ++ { ++ const char* path = NULL; ++ int dirindex = 0; ++ ++ for (unsigned int i = 0; i < format_count; i++) ++ { ++ if (types[i] == elfcpp::DW_LNCT_path) ++ { ++ if (forms[i] == elfcpp::DW_FORM_string) ++ { ++ path = reinterpret_cast<const char*>(lineptr); ++ lineptr += strlen(path) + 1; ++ } ++ else if (forms[i] == elfcpp::DW_FORM_line_strp) ++ { ++ uint64_t offset; ++ if (this->header_.offset_size == 4) ++ offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr); ++ else ++ offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr); ++ typename Reloc_map::const_iterator it ++ = this->reloc_map_.find(lineptr - this->buffer_); ++ if (it != reloc_map_.end()) ++ { ++ if (this->track_relocs_type_ == elfcpp::SHT_RELA) ++ offset = 0; ++ offset += it->second.second; ++ } ++ lineptr += this->header_.offset_size; ++ path = reinterpret_cast<const char*>(this->str_buffer_ ++ + offset); ++ } ++ else ++ return lineptr; ++ } ++ else if (types[i] == elfcpp::DW_LNCT_directory_index) ++ { ++ if (forms[i] == elfcpp::DW_FORM_udata) ++ { ++ dirindex = read_unsigned_LEB_128(lineptr, &len); ++ lineptr += len; ++ } ++ else ++ return lineptr; ++ } ++ else ++ return lineptr; ++ } ++ gold_debug(DEBUG_LOCATION, "File %3d: %s", ++ static_cast<int>(file_list.size()), path); ++ file_list.push_back(std::make_pair(dirindex, path)); ++ } ++ ++ delete[] types; ++ delete[] forms; ++ ++ return lineptr; ++} ++ + // Process a single opcode in the .debug.line structure. + + template<int size, bool big_endian> +@@ -1790,15 +2219,15 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( + + // If the opcode is great than the opcode_base, it is a special + // opcode. Most line programs consist mainly of special opcodes. +- if (opcode >= header_.opcode_base) ++ if (opcode >= this->header_.opcode_base) + { +- opcode -= header_.opcode_base; +- const int advance_address = ((opcode / header_.line_range) +- * header_.min_insn_length); ++ opcode -= this->header_.opcode_base; ++ const int advance_address = ((opcode / this->header_.line_range) ++ * this->header_.min_insn_length); + lsm->address += advance_address; + +- const int advance_line = ((opcode % header_.line_range) +- + header_.line_base); ++ const int advance_line = ((opcode % this->header_.line_range) ++ + this->header_.line_base); + lsm->line_num += advance_line; + lsm->basic_block = true; + *len = oplen; +@@ -1818,13 +2247,13 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( + const uint64_t advance_address + = read_unsigned_LEB_128(start, &templen); + oplen += templen; +- lsm->address += header_.min_insn_length * advance_address; ++ lsm->address += this->header_.min_insn_length * advance_address; + } + break; + + case elfcpp::DW_LNS_advance_line: + { +- const uint64_t advance_line = read_signed_LEB_128(start, &templen); ++ const int64_t advance_line = read_signed_LEB_128(start, &templen); + oplen += templen; + lsm->line_num += advance_line; + } +@@ -1865,9 +2294,9 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( + + case elfcpp::DW_LNS_const_add_pc: + { +- const int advance_address = (header_.min_insn_length +- * ((255 - header_.opcode_base) +- / header_.line_range)); ++ const int advance_address = (this->header_.min_insn_length ++ * ((255 - this->header_.opcode_base) ++ / this->header_.line_range)); + lsm->address += advance_address; + } + break; +@@ -1950,7 +2379,7 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( + default: + { + // Ignore unknown opcode silently +- for (int i = 0; i < header_.std_opcode_lengths[opcode]; i++) ++ for (int i = 0; i < this->header_.std_opcode_lengths[opcode]; i++) + { + size_t templen; + read_unsigned_LEB_128(start, &templen); +@@ -1970,28 +2399,24 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( + template<int size, bool big_endian> + unsigned const char* + Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr, ++ unsigned const char* endptr, + unsigned int shndx) + { + struct LineStateMachine lsm; + +- // LENGTHSTART is the place the length field is based on. It is the +- // point in the header after the initial length field. +- const unsigned char* lengthstart = buffer_; +- +- // In 64 bit dwarf, the initial length is 12 bytes, because of the +- // 0xffffffff at the start. +- if (header_.offset_size == 8) +- lengthstart += 12; +- else +- lengthstart += 4; +- +- while (lineptr < lengthstart + header_.total_length) ++ while (lineptr < endptr) + { +- ResetLineStateMachine(&lsm, header_.default_is_stmt); ++ ResetLineStateMachine(&lsm, this->header_.default_is_stmt); + while (!lsm.end_sequence) + { + size_t oplength; ++ ++ if (lineptr >= endptr) ++ break; ++ + bool add_line = this->process_one_opcode(lineptr, &lsm, &oplength); ++ lineptr += oplength; ++ + if (add_line + && (shndx == -1U || lsm.shndx == -1U || shndx == lsm.shndx)) + { +@@ -2012,11 +2437,10 @@ Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr + map.back().last_line_for_offset = false; + map.push_back(entry); + } +- lineptr += oplength; + } + } + +- return lengthstart + header_.total_length; ++ return endptr; + } + + // Read the relocations into a Reloc_map. +@@ -2057,9 +2481,17 @@ Sized_dwarf_line_info<size, big_endian>::read_line_mappings(unsigned int shndx) + { + const unsigned char* lineptr = this->buffer_; + lineptr = this->read_header_prolog(lineptr); +- lineptr = this->read_header_tables(lineptr); +- lineptr = this->read_lines(lineptr, shndx); +- this->buffer_ = lineptr; ++ if (this->header_.version >= 2 && this->header_.version <= 4) ++ { ++ lineptr = this->read_header_tables_v2(lineptr); ++ lineptr = this->read_lines(lineptr, this->end_of_unit_, shndx); ++ } ++ else if (this->header_.version == 5) ++ { ++ lineptr = this->read_header_tables_v5(lineptr); ++ lineptr = this->read_lines(lineptr, this->end_of_unit_, shndx); ++ } ++ this->buffer_ = this->end_of_unit_; + } + + // Sort the lines numbers, so addr2line can use binary search. +@@ -2215,6 +2647,9 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line( + off_t offset, + std::vector<std::string>* other_lines) + { ++ gold_debug(DEBUG_LOCATION, "do_addr2line: shndx %u offset %08x", ++ shndx, static_cast<int>(offset)); ++ + if (this->data_valid_ == false) + return ""; + +diff --git a/gold/dwarf_reader.h b/gold/dwarf_reader.h +index 80b2231327c..921a1f7c876 100644 +--- a/gold/dwarf_reader.h ++++ b/gold/dwarf_reader.h +@@ -173,11 +173,12 @@ class Dwarf_abbrev_table + // An attribute list entry. + struct Attribute + { +- Attribute(unsigned int a, unsigned int f) +- : attr(a), form(f) ++ Attribute(unsigned int a, unsigned int f, int c) ++ : attr(a), form(f), implicit_const(c) + { } + unsigned int attr; + unsigned int form; ++ int implicit_const; + }; + + // An abbrev code entry. +@@ -190,9 +191,9 @@ class Dwarf_abbrev_table + } + + void +- add_attribute(unsigned int attr, unsigned int form) ++ add_attribute(unsigned int attr, unsigned int form, int implicit_const) + { +- this->attributes.push_back(Attribute(attr, form)); ++ this->attributes.push_back(Attribute(attr, form, implicit_const)); + } + + // The DWARF tag. +@@ -349,14 +350,15 @@ class Dwarf_ranges_table + delete this->ranges_reloc_mapper_; + } + +- // Read the ranges table from an object file. ++ // Fetch the contents of the ranges table from an object file. + bool + read_ranges_table(Relobj* object, + const unsigned char* symtab, + off_t symtab_size, +- unsigned int ranges_shndx); ++ unsigned int ranges_shndx, ++ unsigned int version); + +- // Read the range table from an object file. ++ // Read the DWARF 2/3/4 range table. + Dwarf_range_list* + read_range_list(Relobj* object, + const unsigned char* symtab, +@@ -365,6 +367,15 @@ class Dwarf_ranges_table + unsigned int ranges_shndx, + off_t ranges_offset); + ++ // Read the DWARF 5 rnglists table. ++ Dwarf_range_list* ++ read_range_list_v5(Relobj* object, ++ const unsigned char* symtab, ++ off_t symtab_size, ++ unsigned int address_size, ++ unsigned int ranges_shndx, ++ off_t ranges_offset); ++ + // Look for a relocation at offset OFF in the range table, + // and return the section index and offset of the target. + unsigned int +@@ -490,8 +501,6 @@ class Dwarf_die + unsigned int shndx; + // Block length for block forms. + unsigned int blocklen; +- // Attribute offset for DW_FORM_strp. +- unsigned int attr_off; + } aux; + }; + +@@ -684,6 +693,10 @@ class Dwarf_die + // calls the various visit_xxx() methods for each header. Clients + // should derive a new class from this one and implement the + // visit_compilation_unit() and visit_type_unit() functions. ++// IS_TYPE_UNIT is true if we are reading from a .debug_types section, ++// which is used only in DWARF 4. For DWARF 5, it will be false, ++// and we will determine whether it's a type init when we parse the ++// header. + + class Dwarf_info_reader + { +@@ -695,7 +708,7 @@ class Dwarf_info_reader + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type) +- : is_type_unit_(is_type_unit), object_(object), symtab_(symtab), ++ : object_(object), symtab_(symtab), + symtab_size_(symtab_size), shndx_(shndx), reloc_shndx_(reloc_shndx), + reloc_type_(reloc_type), abbrev_shndx_(0), string_shndx_(0), + buffer_(NULL), buffer_end_(NULL), cu_offset_(0), cu_length_(0), +@@ -703,7 +716,12 @@ class Dwarf_info_reader + abbrev_table_(), ranges_table_(this), + reloc_mapper_(NULL), string_buffer_(NULL), string_buffer_end_(NULL), + owns_string_buffer_(false), string_output_section_offset_(0) +- { } ++ { ++ // For DWARF 4, we infer the unit type from the section name. ++ // For DWARF 5, we will read this from the unit header. ++ this->unit_type_ = ++ (is_type_unit ? elfcpp::DW_UT_type : elfcpp::DW_UT_compile); ++ } + + virtual + ~Dwarf_info_reader() +@@ -714,6 +732,13 @@ class Dwarf_info_reader + delete[] this->string_buffer_; + } + ++ bool ++ is_type_unit() const ++ { ++ return (this->unit_type_ == elfcpp::DW_UT_type ++ || this->unit_type_ == elfcpp::DW_UT_split_type); ++ } ++ + // Begin parsing the debug info. This calls visit_compilation_unit() + // or visit_type_unit() for each compilation or type unit found in the + // section, and visit_die() for each top-level DIE. +@@ -745,6 +770,9 @@ class Dwarf_info_reader + inline typename elfcpp::Valtype_base<valsize>::Valtype + read_from_pointer(const unsigned char** source); + ++ inline typename elfcpp::Valtype_base<32>::Valtype ++ read_3bytes_from_pointer(const unsigned char** source); ++ + // Look for a relocation at offset ATTR_OFF in the dwarf info, + // and return the section index and offset of the target. + unsigned int +@@ -818,12 +846,20 @@ class Dwarf_info_reader + Dwarf_range_list* + read_range_list(unsigned int ranges_shndx, off_t ranges_offset) + { +- return this->ranges_table_.read_range_list(this->object_, +- this->symtab_, +- this->symtab_size_, +- this->address_size_, +- ranges_shndx, +- ranges_offset); ++ if (this->cu_version_ < 5) ++ return this->ranges_table_.read_range_list(this->object_, ++ this->symtab_, ++ this->symtab_size_, ++ this->address_size_, ++ ranges_shndx, ++ ranges_offset); ++ else ++ return this->ranges_table_.read_range_list_v5(this->object_, ++ this->symtab_, ++ this->symtab_size_, ++ this->address_size_, ++ ranges_shndx, ++ ranges_offset); + } + + // Return the object. +@@ -873,8 +909,8 @@ class Dwarf_info_reader + bool + do_read_string_table(unsigned int string_shndx); + +- // True if this is a type unit; false for a compilation unit. +- bool is_type_unit_; ++ // The unit type (DW_UT_xxx). ++ unsigned int unit_type_; + // The object containing the .debug_info or .debug_types input section. + Relobj* object_; + // The ELF symbol table. +@@ -1008,6 +1044,8 @@ class Sized_dwarf_line_info : public Dwarf_line_info + { + if (this->buffer_start_ != NULL) + delete[] this->buffer_start_; ++ if (this->str_buffer_start_ != NULL) ++ delete[] this->str_buffer_start_; + } + + private: +@@ -1030,19 +1068,23 @@ class Sized_dwarf_line_info : public Dwarf_line_info + void + read_relocs(); + +- // Reads the DWARF2/3 header for this line info. Each takes as input ++ // Reads the DWARF header for this line info. Each takes as input + // a starting buffer position, and returns the ending position. + const unsigned char* + read_header_prolog(const unsigned char* lineptr); + + const unsigned char* +- read_header_tables(const unsigned char* lineptr); ++ read_header_tables_v2(const unsigned char* lineptr); ++ ++ const unsigned char* ++ read_header_tables_v5(const unsigned char* lineptr); + +- // Reads the DWARF2/3 line information. If shndx is non-negative, ++ // Reads the DWARF line information. If shndx is non-negative, + // discard all line information that doesn't pertain to the given + // section. + const unsigned char* +- read_lines(const unsigned char* lineptr, unsigned int shndx); ++ read_lines(const unsigned char* lineptr, const unsigned char* endptr, ++ unsigned int shndx); + + // Process a single line info opcode at START using the state + // machine at LSM. Return true if we should define a line using the +@@ -1069,6 +1111,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info + { + off_t total_length; + int version; ++ int address_size; + off_t prologue_length; + int min_insn_length; // insn stands for instruction + int max_ops_per_insn; // Added in DWARF-4. +@@ -1089,6 +1132,20 @@ class Sized_dwarf_line_info : public Dwarf_line_info + // of the buffer. + const unsigned char* buffer_start_; + ++ // str_buffer is the buffer for the line table strings. ++ const unsigned char* str_buffer_; ++ const unsigned char* str_buffer_end_; ++ // If the buffer was allocated temporarily, and therefore must be ++ // deallocated in the dtor, this contains a pointer to the start ++ // of the buffer. ++ const unsigned char* str_buffer_start_; ++ ++ // Pointer to the end of the header_length field (aka prologue_length). ++ const unsigned char* end_of_header_length_; ++ ++ // Pointer to the end of the current compilation unit. ++ const unsigned char* end_of_unit_; ++ + // This has relocations that point into buffer. + Sized_elf_reloc_mapper<size, big_endian>* reloc_mapper_; + // The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA. diff --git a/poky/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch b/poky/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch new file mode 100644 index 000000000..d6117b65a --- /dev/null +++ b/poky/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch @@ -0,0 +1,388 @@ +From d3edaa91d4cf7202ec14342410194841e2f67f12 Mon Sep 17 00:00:00 2001 +From: Alan Modra <amodra@gmail.com> +Date: Fri, 26 Feb 2021 11:30:32 +1030 +Subject: [PATCH] Reinstate various pieces backed out from smart_rename changes + +In the interests of a stable release various last minute smart_rename +patches were backed out of the 2.36 branch. The main reason to +reinstate some of those backed out changes here is to make necessary +followup fixes to commit 8e03235147a9 simple cherry-picks from +mainline. A secondary reason is that ar -M support isn't fixed for +pr26945 without this patch. + + PR 26945 + * ar.c: Don't include libbfd.h. + (write_archive): Replace xmalloc+strcpy with xstrdup. + * arsup.c (temp_name, real_ofd): New static variables. + (ar_open): Use make_tempname and bfd_fdopenw. + (ar_save): Adjust to suit ar_open changes. + * objcopy.c: Don't include libbfd.h. + * rename.c: Rename and reorder variables. + +(cherry picked from commit 95b91a043aeaeb546d2fea556d84a2de1e917770) + +Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d3edaa91d4cf7202ec14342410194841e2f67f12] +CVE: CVE-2021-20197 +Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com> +--- + binutils/ar.c | 6 +- + binutils/arsup.c | 37 ++++++++---- + binutils/bucomm.h | 3 +- + binutils/objcopy.c | 9 +-- + binutils/rename.c | 148 +++++++++++---------------------------------- + 5 files changed, 67 insertions(+), 136 deletions(-) + +diff --git a/binutils/ar.c b/binutils/ar.c +index 45a34e3a6cf..44df48c5c67 100644 +--- a/binutils/ar.c ++++ b/binutils/ar.c +@@ -25,7 +25,6 @@ + + #include "sysdep.h" + #include "bfd.h" +-#include "libbfd.h" + #include "libiberty.h" + #include "progress.h" + #include "getopt.h" +@@ -1255,8 +1254,7 @@ write_archive (bfd *iarch) + bfd *contents_head = iarch->archive_next; + int ofd = -1; + +- old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1); +- strcpy (old_name, bfd_get_filename (iarch)); ++ old_name = xstrdup (bfd_get_filename (iarch)); + new_name = make_tempname (old_name, &ofd); + + if (new_name == NULL) +@@ -1308,7 +1306,7 @@ write_archive (bfd *iarch) + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + +- if (smart_rename (new_name, old_name, 0) != 0) ++ if (smart_rename (new_name, old_name, NULL) != 0) + xexit (1); + free (old_name); + free (new_name); +diff --git a/binutils/arsup.c b/binutils/arsup.c +index 5403a0c5d74..f7ce8f0bc82 100644 +--- a/binutils/arsup.c ++++ b/binutils/arsup.c +@@ -42,6 +42,8 @@ extern int deterministic; + + static bfd *obfd; + static char *real_name; ++static char *temp_name; ++static int real_ofd; + static FILE *outfile; + + static void +@@ -149,27 +151,24 @@ maybequit (void) + void + ar_open (char *name, int t) + { +- char *tname; +- const char *bname = lbasename (name); +- real_name = name; ++ real_name = xstrdup (name); ++ temp_name = make_tempname (real_name, &real_ofd); + +- /* Prepend tmp- to the beginning, to avoid file-name clashes after +- truncation on filesystems with limited namespaces (DOS). */ +- if (asprintf (&tname, "%.*stmp-%s", (int) (bname - name), name, bname) == -1) ++ if (temp_name == NULL) + { +- fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"), ++ fprintf (stderr, _("%s: Can't open temporary file (%s)\n"), + program_name, strerror(errno)); + maybequit (); + return; + } + +- obfd = bfd_openw (tname, NULL); ++ obfd = bfd_fdopenw (temp_name, NULL, real_ofd); + + if (!obfd) + { + fprintf (stderr, + _("%s: Can't open output archive %s\n"), +- program_name, tname); ++ program_name, temp_name); + + maybequit (); + } +@@ -344,16 +343,30 @@ ar_save (void) + } + else + { +- char *ofilename = xstrdup (bfd_get_filename (obfd)); ++ struct stat target_stat; + + if (deterministic > 0) + obfd->flags |= BFD_DETERMINISTIC_OUTPUT; + + bfd_close (obfd); + +- smart_rename (ofilename, real_name, 0); ++ if (stat (real_name, &target_stat) != 0) ++ { ++ /* The temp file created in ar_open has mode 0600 as per mkstemp. ++ Create the real empty output file here so smart_rename will ++ update the mode according to the process umask. */ ++ obfd = bfd_openw (real_name, NULL); ++ if (obfd != NULL) ++ { ++ bfd_set_format (obfd, bfd_archive); ++ bfd_close (obfd); ++ } ++ } ++ ++ smart_rename (temp_name, real_name, NULL); + obfd = 0; +- free (ofilename); ++ free (temp_name); ++ free (real_name); + } + } + +diff --git a/binutils/bucomm.h b/binutils/bucomm.h +index 91f6a5b228f..aa7e33d8cd1 100644 +--- a/binutils/bucomm.h ++++ b/binutils/bucomm.h +@@ -71,7 +71,8 @@ extern void print_version (const char *); + /* In rename.c. */ + extern void set_times (const char *, const struct stat *); + +-extern int smart_rename (const char *, const char *, int); ++extern int smart_rename (const char *, const char *, struct stat *); ++ + + /* In libiberty. */ + void *xmalloc (size_t); +diff --git a/binutils/objcopy.c b/binutils/objcopy.c +index eab3b6db585..73aa8bc2514 100644 +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c +@@ -20,7 +20,6 @@ + + #include "sysdep.h" + #include "bfd.h" +-#include "libbfd.h" + #include "progress.h" + #include "getopt.h" + #include "libiberty.h" +@@ -4861,12 +4860,10 @@ strip_main (int argc, char *argv[]) + output_target, NULL); + if (status == 0) + { +- if (preserve_dates) +- set_times (tmpname, &statbuf); + if (output_file != tmpname) + status = (smart_rename (tmpname, + output_file ? output_file : argv[i], +- preserve_dates) != 0); ++ preserve_dates ? &statbuf : NULL) != 0); + if (status == 0) + status = hold_status; + } +@@ -5931,11 +5928,9 @@ copy_main (int argc, char *argv[]) + output_target, input_arch); + if (status == 0) + { +- if (preserve_dates) +- set_times (tmpname, &statbuf); + if (tmpname != output_filename) + status = (smart_rename (tmpname, input_filename, +- preserve_dates) != 0); ++ preserve_dates ? &statbuf : NULL) != 0); + } + else + unlink_if_ordinary (tmpname); +diff --git a/binutils/rename.c b/binutils/rename.c +index 65ad5bf52c4..72a9323d72c 100644 +--- a/binutils/rename.c ++++ b/binutils/rename.c +@@ -24,14 +24,9 @@ + + #ifdef HAVE_GOOD_UTIME_H + #include <utime.h> +-#else /* ! HAVE_GOOD_UTIME_H */ +-#ifdef HAVE_UTIMES ++#elif defined HAVE_UTIMES + #include <sys/time.h> +-#endif /* HAVE_UTIMES */ +-#endif /* ! HAVE_GOOD_UTIME_H */ +- +-#if ! defined (_WIN32) || defined (__CYGWIN32__) +-static int simple_copy (const char *, const char *); ++#endif + + /* The number of bytes to copy at once. */ + #define COPY_BUF 8192 +@@ -82,7 +77,6 @@ simple_copy (const char *from, const char *to) + } + return 0; + } +-#endif /* __CYGWIN32__ or not _WIN32 */ + + /* Set the times of the file DESTINATION to be the same as those in + STATBUF. */ +@@ -91,122 +85,52 @@ void + set_times (const char *destination, const struct stat *statbuf) + { + int result; +- +- { + #ifdef HAVE_GOOD_UTIME_H +- struct utimbuf tb; +- +- tb.actime = statbuf->st_atime; +- tb.modtime = statbuf->st_mtime; +- result = utime (destination, &tb); +-#else /* ! HAVE_GOOD_UTIME_H */ +-#ifndef HAVE_UTIMES +- long tb[2]; +- +- tb[0] = statbuf->st_atime; +- tb[1] = statbuf->st_mtime; +- result = utime (destination, tb); +-#else /* HAVE_UTIMES */ +- struct timeval tv[2]; +- +- tv[0].tv_sec = statbuf->st_atime; +- tv[0].tv_usec = 0; +- tv[1].tv_sec = statbuf->st_mtime; +- tv[1].tv_usec = 0; +- result = utimes (destination, tv); +-#endif /* HAVE_UTIMES */ +-#endif /* ! HAVE_GOOD_UTIME_H */ +- } ++ struct utimbuf tb; ++ ++ tb.actime = statbuf->st_atime; ++ tb.modtime = statbuf->st_mtime; ++ result = utime (destination, &tb); ++#elif defined HAVE_UTIMES ++ struct timeval tv[2]; ++ ++ tv[0].tv_sec = statbuf->st_atime; ++ tv[0].tv_usec = 0; ++ tv[1].tv_sec = statbuf->st_mtime; ++ tv[1].tv_usec = 0; ++ result = utimes (destination, tv); ++#else ++ long tb[2]; ++ ++ tb[0] = statbuf->st_atime; ++ tb[1] = statbuf->st_mtime; ++ result = utime (destination, tb); ++#endif + + if (result != 0) + non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); + } + +-#ifndef S_ISLNK +-#ifdef S_IFLNK +-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +-#else +-#define S_ISLNK(m) 0 +-#define lstat stat +-#endif +-#endif +- +-/* Rename FROM to TO, copying if TO is a link. +- Return 0 if ok, -1 if error. */ ++/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL, ++ is used to fix up timestamps. Return 0 if ok, -1 if error. ++ At one time this function renamed files, but file permissions are ++ tricky to update given the number of different schemes used by ++ various systems. So now we just copy. */ + + int +-smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED) ++smart_rename (const char *from, const char *to, ++ struct stat *target_stat) + { +- bfd_boolean exists; +- struct stat s; +- int ret = 0; +- +- exists = lstat (to, &s) == 0; +- +-#if defined (_WIN32) && !defined (__CYGWIN32__) +- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but +- fail instead. Also, chown is not present. */ ++ int ret; + +- if (exists) +- remove (to); +- +- ret = rename (from, to); ++ ret = simple_copy (from, to); + if (ret != 0) +- { +- /* We have to clean up here. */ +- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); +- unlink (from); +- } +-#else +- /* Use rename only if TO is not a symbolic link and has +- only one hard link, and we have permission to write to it. */ +- if (! exists +- || (!S_ISLNK (s.st_mode) +- && S_ISREG (s.st_mode) +- && (s.st_mode & S_IWUSR) +- && s.st_nlink == 1) +- ) +- { +- ret = rename (from, to); +- if (ret == 0) +- { +- if (exists) +- { +- /* Try to preserve the permission bits and ownership of +- TO. First get the mode right except for the setuid +- bit. Then change the ownership. Then fix the setuid +- bit. We do the chmod before the chown because if the +- chown succeeds, and we are a normal user, we won't be +- able to do the chmod afterward. We don't bother to +- fix the setuid bit first because that might introduce +- a fleeting security problem, and because the chown +- will clear the setuid bit anyhow. We only fix the +- setuid bit if the chown succeeds, because we don't +- want to introduce an unexpected setuid file owned by +- the user running objcopy. */ +- chmod (to, s.st_mode & 0777); +- if (chown (to, s.st_uid, s.st_gid) >= 0) +- chmod (to, s.st_mode & 07777); +- } +- } +- else +- { +- /* We have to clean up here. */ +- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); +- unlink (from); +- } +- } +- else +- { +- ret = simple_copy (from, to); +- if (ret != 0) +- non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); ++ non_fatal (_("unable to copy file '%s'; reason: %s"), ++ to, strerror (errno)); + +- if (preserve_dates) +- set_times (to, &s); +- unlink (from); +- } +-#endif /* _WIN32 && !__CYGWIN32__ */ ++ if (target_stat != NULL) ++ set_times (to, target_stat); ++ unlink (from); + + return ret; + } +-- +2.17.1 + diff --git a/poky/meta/recipes-devtools/binutils/binutils_2.36.bb b/poky/meta/recipes-devtools/binutils/binutils_2.36.bb index a50d2ee7e..ee9617de1 100644 --- a/poky/meta/recipes-devtools/binutils/binutils_2.36.bb +++ b/poky/meta/recipes-devtools/binutils/binutils_2.36.bb @@ -25,7 +25,7 @@ EXTRA_OECONF_class-native = "--enable-targets=all \ --disable-sim \ --disable-werror" -PACKAGECONFIG ??= "" +PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'debuginfod', d)}" PACKAGECONFIG[debuginfod] = "--with-debuginfod, --without-debuginfod, elfutils" # gcc9.0 end up mis-compiling libbfd.so with O2 which then crashes on target # So remove -O2 and use -Os as workaround |