[prev in list] [next in list] [prev in thread] [next in thread]
List: openembedded-core
Subject: Re: [OE-core] [kirkstone][PATCH] binutils : Fix CVE-2023-22608
From: "Shinde, Yash" <Yash.Shinde () windriver ! com>
Date: 2023-02-28 6:10:22
Message-ID: SJ1PR11MB6129A763D8105BB88C04C8D7EBAC9 () SJ1PR11MB6129 ! namprd11 ! prod ! outlook ! com
[Download RAW message or body]
Yes, the actual fix is 0020-CVE-2023-22608-3.patch. The other two files are the \
dependent patch files required for this patch to apply. If these are excluded, the \
build gives errors in do_compile task due to missing code dependencies.
Regards,
Yash
From: MacLeod, Randy<mailto:Randy.MacLeod@windriver.com>
Sent: 28 February 2023 07:30
To: Yash Shinde<mailto:yashinde145@gmail.com>; \
openembedded-core@lists.openembedded.org<mailto:openembedded-core@lists.openembedded.org>; \
steve@sakoman.com<mailto:steve@sakoman.com>
Cc: Kallapa, Umesh<mailto:Umesh.Kallapa@windriver.com>; Gowda, \
Naveen<mailto:Naveen.Gowda@windriver.com>; Kokkonda, \
Sundeep<mailto:Sundeep.Kokkonda@windriver.com>; Moodalappa, \
Shivaprasad<mailto:Shivaprasad.Moodalappa@windriver.com>; Shinde, \
Yash<mailto:Yash.Shinde@windriver.com>
Subject: Re: [kirkstone][PATCH] binutils : Fix CVE-2023-22608
On 2023-02-26 04:11, Yash Shinde wrote:
From: Yash Shinde <Yash.Shinde@windriver.com><mailto:Yash.Shinde@windriver.com>
Upstream-Status: Backport \
[https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09]
Signed-off-by: Yash Shinde \
<Yash.Shinde@windriver.com><mailto:Yash.Shinde@windriver.com>
---
.../binutils/binutils-2.38.inc | 3 +
.../binutils/0020-CVE-2023-22608-1.patch | 502 ++++++++++++++++++
.../binutils/0020-CVE-2023-22608-2.patch | 211 ++++++++
.../binutils/0020-CVE-2023-22608-3.patch | 33 ++
This is a large patch so I took a look at it.
The actual fix is: 0020-CVE-2023-22608-3.patch
https://sourceware.org/git/?p=binutils-gdb.git;a=blobdiff;f=bfd/dwarf2.c;h=88335cb4fb0 \
dddc3b1ca8a1d76c32b88ff85aa89;hp=b608afbc0cf260e98e2f87ab6d55c935937b2810;hb=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09;hpb=8fbad19958c9b9c06a710bf7d6589d52f1ed8a64
which is just a few lines.
Unfortunately we do need the other two, rather large patches to make that apply it \
seems.
The patch that adds a trie seems like a feature but the code is all (I think) file
scope local structs with static functions so as far as the ABI stability, it seems \
fine to backport. It will change the memory footprint:
commit b43771b045fb5616da3964f2994eefbe8ae70d32
Author: Steinar H. Gunderson <sesse@google.com><mailto:sesse@google.com>
Date: Fri May 20 10:10:34 2022
add a trie to map quickly from address range to compilation unit
When using perf to profile large binaries, _bfd_dwarf2_find_nearest_line()
becomes a hotspot, as perf wants to get line number information
(for inline-detection purposes) for each and every sample. In Chromium
in particular (the content_shell binary), this entails going through
475k address ranges, which takes a long time when done repeatedly.
Add a radix-256 trie over the address space to quickly map address to
compilation unit spaces; for content_shell, which is 1.6 GB when some
(but not full) debug information turned is on, we go from 6 ms to
0.006 ms (6 µs) for each lookup from address to compilation unit, a 1000x
speedup.
There is a modest RAM increase of 180 MB in this binary (the existing
linked list over ranges uses about 10 MB, and the entire perf job uses
between 2–3 GB for a medium-size profile); for smaller binaries with few
ranges, there should be hardly any extra RAM usage at all.
../Randy
4 files changed, 749 insertions(+)
create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch
create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch
create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch
diff --git a/meta/recipes-devtools/binutils/binutils-2.38.inc \
b/meta/recipes-devtools/binutils/binutils-2.38.inc
index 0a4a0d7bc1..30a34d7ba4 100644
--- a/meta/recipes-devtools/binutils/binutils-2.38.inc
+++ b/meta/recipes-devtools/binutils/binutils-2.38.inc
@@ -43,5 +43,8 @@ SRC_URI = "\
file://0018-CVE-2022-38128-2.patch \
file://0018-CVE-2022-38128-3.patch \
file://0019-CVE-2022-4285.patch \
+ file://0020-CVE-2023-22608-1.patch \
+ file://0020-CVE-2023-22608-2.patch \
+ file://0020-CVE-2023-22608-3.patch \
"
S = "${WORKDIR}/git"
diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch
new file mode 100644
index 0000000000..dd3d533d0d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch
@@ -0,0 +1,502 @@
+From a79c274dad99863f58b9ed627b38908daadb6d7e Mon Sep 17 00:00:00 2001
+From: "Steinar H. Gunderson" <sesse@google.com><mailto:sesse@google.com>
+Date: Fri, 20 May 2022 16:10:34 +0200
+Subject: [PATCH] add a trie to map quickly from address range to compilation
+ unit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When using perf to profile large binaries, _bfd_dwarf2_find_nearest_line()
+becomes a hotspot, as perf wants to get line number information
+(for inline-detection purposes) for each and every sample. In Chromium
+in particular (the content_shell binary), this entails going through
+475k address ranges, which takes a long time when done repeatedly.
+
+Add a radix-256 trie over the address space to quickly map address to
+compilation unit spaces; for content_shell, which is 1.6 GB when some
+(but not full) debug information turned is on, we go from 6 ms to
+0.006 ms (6 µs) for each lookup from address to compilation unit, a 1000x
+speedup.
+
+There is a modest RAM increase of 180 MB in this binary (the existing
+linked list over ranges uses about 10 MB, and the entire perf job uses
+between 2-3 GB for a medium-size profile); for smaller binaries with few
+ranges, there should be hardly any extra RAM usage at all.
+
+Upstream-Status: Backport \
[https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=b43771b045fb5616da3964f2994eefbe8ae70d32]
+
+CVE: CVE-2023-22608
+
+Signed-off-by: Yash Shinde \
<Yash.Shinde@windriver.com><mailto:Yash.Shinde@windriver.com>
+
+---
+ bfd/dwarf2.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 312 insertions(+), 14 deletions(-)
+
+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
+index fdf071c3..0ae50a37 100644
+--- a/bfd/dwarf2.c
++++ b/bfd/dwarf2.c
+@@ -82,6 +82,77 @@ struct adjusted_section
+ bfd_vma adj_vma;
+ };
+
++/* A trie to map quickly from address range to compilation unit.
++
++ This is a fairly standard radix-256 trie, used to quickly locate which
++ compilation unit any given address belongs to. Given that each compilation
++ unit may register hundreds of very small and unaligned ranges (which may
++ potentially overlap, due to inlining and other concerns), and a large
++ program may end up containing hundreds of thousands of such ranges, we cannot
++ scan through them linearly without undue slowdown.
++
++ We use a hybrid trie to avoid memory explosion: There are two types of trie
++ nodes, leaves and interior nodes. (Almost all nodes are leaves, so they
++ take up the bulk of the memory usage.) Leaves contain a simple array of
++ ranges (high/low address) and which compilation unit contains those ranges,
++ and when we get to a leaf, we scan through it linearly. Interior nodes
++ contain pointers to 256 other nodes, keyed by the next byte of the address.
++ So for a 64-bit address like 0x1234567abcd, we would start at the root and go
++ down child[0x00]->child[0x00]->child[0x01]->child[0x23]->child[0x45] etc.,
++ until we hit a leaf. (Nodes are, in general, leaves until they exceed the
++ default allocation of 16 elements, at which point they are converted to
++ interior node if possible.) This gives us near-constant lookup times;
++ the only thing that can be costly is if there are lots of overlapping ranges
++ within a single 256-byte segment of the binary, in which case we have to
++ scan through them all to find the best match.
++
++ For a binary with few ranges, we will in practice only have a single leaf
++ node at the root, containing a simple array. Thus, the scheme is efficient
++ for both small and large binaries.
++ */
++
++/* Experiments have shown 16 to be a memory-efficient default leaf size.
++ The only case where a leaf will hold more memory than this, is at the
++ bottomost level (covering 256 bytes in the binary), where we'll expand
++ the leaf to be able to hold more ranges if needed.
++ */
++#define TRIE_LEAF_SIZE 16
++
++/* All trie_node pointers will really be trie_leaf or trie_interior,
++ but they have this common head. */
++struct trie_node
++{
++ /* If zero, we are an interior node.
++ Otherwise, how many ranges we have room for in this leaf. */
++ unsigned int num_room_in_leaf;
++};
++
++struct trie_leaf
++{
++ struct trie_node head;
++ unsigned int num_stored_in_leaf;
++ struct {
++ struct comp_unit *unit;
++ bfd_vma low_pc, high_pc;
++ } ranges[TRIE_LEAF_SIZE];
++};
++
++struct trie_interior
++{
++ struct trie_node head;
++ struct trie_node *children[256];
++};
++
++static struct trie_node *alloc_trie_leaf (bfd *abfd)
++{
++ struct trie_leaf *leaf =
++ bfd_zalloc (abfd, sizeof (struct trie_leaf));
++ if (leaf == NULL)
++ return NULL;
++ leaf->head.num_room_in_leaf = TRIE_LEAF_SIZE;
++ return &leaf->head;
++}
++
+ struct dwarf2_debug_file
+ {
+ /* The actual bfd from which debug info was loaded. Might be
+@@ -139,6 +210,9 @@ struct dwarf2_debug_file
+ /* A list of all previously read comp_units. */
+ struct comp_unit *all_comp_units;
+
++ /* A list of all previously read comp_units with no ranges (yet). */
++ struct comp_unit *all_comp_units_without_ranges;
++
+ /* Last comp unit in list above. */
+ struct comp_unit *last_comp_unit;
+
+@@ -147,6 +221,9 @@ struct dwarf2_debug_file
+
+ /* Hash table to map offsets to decoded abbrevs. */
+ htab_t abbrev_offsets;
++
++ /* Root of a trie to map addresses to compilation units. */
++ struct trie_node *trie_root;
+ };
+
+ struct dwarf2_debug
+@@ -220,6 +297,11 @@ struct comp_unit
+ /* Chain the previously read compilation units. */
+ struct comp_unit *next_unit;
+
++ /* Chain the previously read compilation units that have no ranges yet.
++ We scan these separately when we have a trie over the ranges.
++ Unused if arange.high != 0. */
++ struct comp_unit *next_unit_without_ranges;
++
+ /* Likewise, chain the compilation unit read after this one.
+ The comp units are stored in reversed reading order. */
+ struct comp_unit *prev_unit;
+@@ -296,6 +378,10 @@ struct comp_unit
+
+ /* TRUE if symbols are cached in hash table for faster lookup by name. */
+ bool cached;
++
++ /* Used when iterating over trie leaves to know which units we have
++ already seen in this iteration. */
++ bool mark;
+ };
+
+ /* This data structure holds the information of an abbrev. */
+@@ -1766,9 +1852,189 @@ concat_filename (struct line_info_table *table, unsigned int \
file)
+ return strdup (filename);
+ }
+
++/* Number of bits in a bfd_vma. */
++#define VMA_BITS (8 * sizeof (bfd_vma))
++
++/* Check whether [low1, high1) can be combined with [low2, high2),
++ i.e., they touch or overlap. */
++static bool ranges_overlap (bfd_vma low1,
++ bfd_vma high1,
++ bfd_vma low2,
++ bfd_vma high2)
++{
++ if (low1 == low2 || high1 == high2)
++ return true;
++
++ /* Sort so that low1 is below low2. */
++ if (low1 > low2)
++ {
++ bfd_vma tmp;
++
++ tmp = low1;
++ low1 = low2;
++ low2 = tmp;
++
++ tmp = high1;
++ high1 = high2;
++ high2 = tmp;
++ }
++
++ /* We touch iff low2 == high1.
++ We overlap iff low2 is within [low1, high1). */
++ return (low2 <= high1);
++}
++
++/* Insert an address range in the trie mapping addresses to compilation units.
++ Will return the new trie node (usually the same as is being sent in, but
++ in case of a leaf-to-interior conversion, or expansion of a leaf, it may be
++ different), or NULL on failure.
++ */
++static struct trie_node *insert_arange_in_trie(bfd *abfd,
++ struct trie_node *trie,
++ bfd_vma trie_pc,
++ unsigned int trie_pc_bits,
++ struct comp_unit *unit,
++ bfd_vma low_pc,
++ bfd_vma high_pc)
++{
++ bfd_vma clamped_low_pc, clamped_high_pc;
++ int ch, from_ch, to_ch;
++ bool is_full_leaf = false;
++
++ /* See if we can extend any of the existing ranges. This merging
++ isn't perfect (if merging opens up the possibility of merging two existing
++ ranges, we won't find them), but it takes the majority of the cases. */
++ if (trie->num_room_in_leaf > 0)
++ {
++ struct trie_leaf *leaf = (struct trie_leaf *) trie;
++ unsigned int i;
++
++ for (i = 0; i < leaf->num_stored_in_leaf; ++i)
++ {
++ if (leaf->ranges[i].unit == unit &&
++ ranges_overlap(low_pc, high_pc,
++ leaf->ranges[i].low_pc, leaf->ranges[i].high_pc))
++ {
++ if (low_pc < leaf->ranges[i].low_pc)
++ leaf->ranges[i].low_pc = low_pc;
++ if (high_pc > leaf->ranges[i].high_pc)
++ leaf->ranges[i].high_pc = high_pc;
++ return trie;
++ }
++ }
++
++ is_full_leaf = leaf->num_stored_in_leaf == trie->num_room_in_leaf;
++ }
++
++ /* If we're a leaf with no more room and we're _not_ at the bottom,
++ convert to an interior node. */
++ if (is_full_leaf && trie_pc_bits < VMA_BITS)
++ {
++ const struct trie_leaf *leaf = (struct trie_leaf *) trie;
++ unsigned int i;
++
++ trie = bfd_zalloc (abfd, sizeof (struct trie_interior));
++ if (!trie)
++ return NULL;
++ is_full_leaf = false;
++
++ /* TODO: If we wanted to save a little more memory at the cost of
++ complexity, we could have reused the old leaf node as one of the
++ children of the new interior node, instead of throwing it away. */
++ for (i = 0; i < leaf->num_stored_in_leaf; ++i)
++ {
++ if (!insert_arange_in_trie (abfd, trie, trie_pc, trie_pc_bits,
++ leaf->ranges[i].unit, leaf->ranges[i].low_pc,
++ leaf->ranges[i].high_pc))
++ return NULL;
++ }
++ }
++
++ /* If we're a leaf with no more room and we _are_ at the bottom,
++ we have no choice but to just make it larger. */
++ if (is_full_leaf)
++ {
++ const struct trie_leaf *leaf = (struct trie_leaf *) trie;
++ unsigned int new_room_in_leaf = trie->num_room_in_leaf * 2;
++ struct trie_leaf *new_leaf;
++
++ new_leaf = bfd_zalloc (abfd,
++ sizeof (struct trie_leaf) +
++ (new_room_in_leaf - TRIE_LEAF_SIZE) * sizeof (leaf->ranges[0]));
++ new_leaf->head.num_room_in_leaf = new_room_in_leaf;
++ new_leaf->num_stored_in_leaf = leaf->num_stored_in_leaf;
++
++ memcpy (new_leaf->ranges,
++ leaf->ranges,
++ leaf->num_stored_in_leaf * sizeof (leaf->ranges[0]));
++ trie = &new_leaf->head;
++ is_full_leaf = false;
++
++ /* Now the insert below will go through. */
++ }
++
++ /* If we're a leaf (now with room), we can just insert at the end. */
++ if (trie->num_room_in_leaf > 0)
++ {
++ struct trie_leaf *leaf = (struct trie_leaf *) trie;
++
++ unsigned int i = leaf->num_stored_in_leaf++;
++ leaf->ranges[i].unit = unit;
++ leaf->ranges[i].low_pc = low_pc;
++ leaf->ranges[i].high_pc = high_pc;
++ return trie;
++ }
++
++ /* Now we are definitely an interior node, so recurse into all
++ the relevant buckets. */
++
++ /* Clamp the range to the current trie bucket. */
++ clamped_low_pc = low_pc;
++ clamped_high_pc = high_pc;
++ if (trie_pc_bits > 0)
++ {
++ bfd_vma bucket_high_pc =
++ trie_pc + ((bfd_vma)-1 >> trie_pc_bits); /* Inclusive. */
++ if (clamped_low_pc < trie_pc)
++ clamped_low_pc = trie_pc;
++ if (clamped_high_pc > bucket_high_pc)
++ clamped_high_pc = bucket_high_pc;
++ }
++
++ /* Insert the ranges in all buckets that it spans. */
++ from_ch = (clamped_low_pc >> (VMA_BITS - trie_pc_bits - 8)) & 0xff;
++ to_ch = ((clamped_high_pc - 1) >> (VMA_BITS - trie_pc_bits - 8)) & 0xff;
++ for (ch = from_ch; ch <= to_ch; ++ch)
++ {
++ struct trie_interior *interior = (struct trie_interior *) trie;
++ struct trie_node *child = interior->children[ch];
++
++ if (child == NULL)
++ {
++ child = alloc_trie_leaf (abfd);
++ if (!child)
++ return NULL;
++ }
++ child = insert_arange_in_trie (abfd,
++ child,
++ trie_pc + ((bfd_vma)ch << (VMA_BITS - trie_pc_bits - 8)),
++ trie_pc_bits + 8,
++ unit,
++ low_pc,
++ high_pc);
++ if (!child)
++ return NULL;
++
++ interior->children[ch] = child;
++ }
++
++ return trie;
++}
++
++
+ static bool
+-arange_add (const struct comp_unit *unit, struct arange *first_arange,
+- bfd_vma low_pc, bfd_vma high_pc)
++arange_add (struct comp_unit *unit, struct arange *first_arange,
++ struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc)
+ {
+ struct arange *arange;
+
+@@ -1776,6 +2042,19 @@ arange_add (const struct comp_unit *unit, struct arange \
*first_arange,
+ if (low_pc == high_pc)
+ return true;
+
++ if (trie_root != NULL)
++ {
++ *trie_root = insert_arange_in_trie (unit->file->bfd_ptr,
++ *trie_root,
++ 0,
++ 0,
++ unit,
++ low_pc,
++ high_pc);
++ if (*trie_root == NULL)
++ return false;
++ }
++
+ /* If the first arange is empty, use it. */
+ if (first_arange->high == 0)
+ {
+@@ -2410,7 +2689,8 @@ decode_line_info (struct comp_unit *unit)
+ low_pc = address;
+ if (address > high_pc)
+ high_pc = address;
+- if (!arange_add (unit, &unit->arange, low_pc, high_pc))
++ if (!arange_add (unit, &unit->arange, &unit->file->trie_root,
++ low_pc, high_pc))
+ goto line_fail;
+ break;
+ case DW_LNE_set_address:
+@@ -3134,7 +3414,7 @@ find_abstract_instance (struct comp_unit *unit,
+
+ static bool
+ read_ranges (struct comp_unit *unit, struct arange *arange,
+- bfd_uint64_t offset)
++ struct trie_node **trie_root, bfd_uint64_t offset)
+ {
+ bfd_byte *ranges_ptr;
+ bfd_byte *ranges_end;
+@@ -3169,7 +3449,7 @@ read_ranges (struct comp_unit *unit, struct arange *arange,
+ base_address = high_pc;
+ else
+ {
+- if (!arange_add (unit, arange,
++ if (!arange_add (unit, arange, trie_root,
+ base_address + low_pc, base_address + high_pc))
+ return false;
+ }
+@@ -3179,7 +3459,7 @@ read_ranges (struct comp_unit *unit, struct arange *arange,
+
+ static bool
+ read_rnglists (struct comp_unit *unit, struct arange *arange,
+- bfd_uint64_t offset)
++ struct trie_node **trie_root, bfd_uint64_t offset)
+ {
+ bfd_byte *rngs_ptr;
+ bfd_byte *rngs_end;
+@@ -3253,19 +3533,19 @@ read_rnglists (struct comp_unit *unit, struct arange \
*arange,
+ return false;
+ }
+
+- if (!arange_add (unit, arange, low_pc, high_pc))
++ if (!arange_add (unit, arange, trie_root, low_pc, high_pc))
+ return false;
+ }
+ }
+
+ static bool
+ read_rangelist (struct comp_unit *unit, struct arange *arange,
+- bfd_uint64_t offset)
++ struct trie_node **trie_root, bfd_uint64_t offset)
+ {
+ if (unit->version <= 4)
+- return read_ranges (unit, arange, offset);
++ return read_ranges (unit, arange, trie_root, offset);
+ else
+- return read_rnglists (unit, arange, offset);
++ return read_rnglists (unit, arange, trie_root, offset);
+ }
+
+ static struct funcinfo *
+@@ -3563,7 +3843,8 @@ scan_unit_for_symbols (struct comp_unit *unit)
+
+ case DW_AT_ranges:
+ if (is_int_form (&attr)
+- && !read_rangelist (unit, &func->arange, attr.u.val))
++ && !read_rangelist (unit, &func->arange,
++ &unit->file->trie_root, attr.u.val))
+ goto fail;
+ break;
+
+@@ -3679,7 +3960,8 @@ scan_unit_for_symbols (struct comp_unit *unit)
+
+ if (func && high_pc != 0)
+ {
+- if (!arange_add (unit, &func->arange, low_pc, high_pc))
++ if (!arange_add (unit, &func->arange, &unit->file->trie_root,
++ low_pc, high_pc))
+ goto fail;
+ }
+ }
+@@ -3874,7 +4156,8 @@ parse_comp_unit (struct dwarf2_debug *stash,
+
+ case DW_AT_ranges:
+ if (is_int_form (&attr)
+- && !read_rangelist (unit, &unit->arange, attr.u.val))
++ && !read_rangelist (unit, &unit->arange,
++ &unit->file->trie_root, attr.u.val))
+ return NULL;
+ break;
+
+@@ -3916,7 +4199,8 @@ parse_comp_unit (struct dwarf2_debug *stash,
+ high_pc += low_pc;
+ if (high_pc != 0)
+ {
+- if (!arange_add (unit, &unit->arange, low_pc, high_pc))
++ if (!arange_add (unit, &unit->arange, &unit->file->trie_root,
++ low_pc, high_pc))
+ return NULL;
+ }
+
+@@ -4747,6 +5031,14 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
+ if (!stash->alt.abbrev_offsets)
+ return false;
+
++ stash->f.trie_root = alloc_trie_leaf (abfd);
++ if (!stash->f.trie_root)
++ return false;
++
++ stash->alt.trie_root = alloc_trie_leaf (abfd);
++ if (!stash->alt.trie_root)
++ return false;
++
+ *pinfo = stash;
+
+ if (debug_bfd == NULL)
+@@ -4918,6 +5210,12 @@ stash_comp_unit (struct dwarf2_debug *stash, struct \
dwarf2_debug_file *file)
+ each->next_unit = file->all_comp_units;
+ file->all_comp_units = each;
+
++ if (each->arange.high == 0)
++ {
++ each->next_unit_without_ranges = file->all_comp_units_without_ranges;
++ file->all_comp_units_without_ranges = each->next_unit_without_ranges;
++ }
++
+ file->info_ptr += length;
+ return each;
+ }
diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch
new file mode 100644
index 0000000000..8ffb500c1d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch
@@ -0,0 +1,211 @@
+From 73e97e32e1428d63d81d971176772ae69397a1a0 Mon Sep 17 00:00:00 2001
+From: Nick Clifton <nickc@redhat.com><mailto:nickc@redhat.com>
+Date: Tue, 30 Aug 2022 16:01:20 +0100
+Subject: [PATCH] BFD library: Use entry 0 in directory and filename tables of
+ DWARF-5 debug info.
+
+ PR 29529
+ * dwarf2.c (struct line_info_table): Add new field:
+ use_dir_and_file_0.
+ (concat_filename): Use new field to help select the correct table
+ slot.
+ (read_formatted_entries): Do not skip entry 0.
+ (decode_line_info): Set new field depending upon the version of
+ DWARF being parsed. Initialise filename based upon the setting of
+ the new field.
+
+Upstream-Status: Backport \
[https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=37833b966576c5d25e797ea3b6c33d0459a71892]
+CVE: CVE-2023-22608
+
+Signed-off-by: Yash Shinde \
<Yash.Shinde@windriver.com><mailto:Yash.Shinde@windriver.com>
+
+---
+ bfd/ChangeLog | 12 +++++
+ bfd/dwarf2.c | 86 ++++++++++++++++++++----------
+ ld/ChangeLog | 5 ++
+ ld/testsuite/ld-x86-64/pr27587.err | 2 +-
+ 4 files changed, 76 insertions(+), 29 deletions(-)
+
+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
+index 0ae50a37..b7839ad6 100644
+--- a/bfd/dwarf2.c
++++ b/bfd/dwarf2.c
+@@ -1571,6 +1571,7 @@ struct line_info_table
+ unsigned int num_files;
+ unsigned int num_dirs;
+ unsigned int num_sequences;
++ bool use_dir_and_file_0;
+ char * comp_dir;
+ char ** dirs;
+ struct fileinfo* files;
+@@ -1791,16 +1792,30 @@ concat_filename (struct line_info_table *table, unsigned int \
file)
+ {
+ char *filename;
+
+- if (table == NULL || file - 1 >= table->num_files)
++ /* Pre DWARF-5 entry 0 in the directory and filename tables was not used.
++ So in order to save space in the tables used here the info for, eg
++ directory 1 is stored in slot 0 of the directory table, directory 2
++ in slot 1 and so on.
++
++ Starting with DWARF-5 the 0'th entry is used so there is a one to one
++ mapping between DWARF slots and internal table entries. */
++ if (! table->use_dir_and_file_0)
+ {
+- /* FILE == 0 means unknown. */
+- if (file)
+- _bfd_error_handler
+- (_("DWARF error: mangled line number section (bad file number)"));
++ /* Pre DWARF-5, FILE == 0 means unknown. */
++ if (file == 0)
++ return strdup ("<unknown>");
++ -- file;
++ }
++
++ if (table == NULL || file >= table->num_files)
++ {
++ _bfd_error_handler
++ (_("DWARF error: mangled line number section (bad file number)"));
+ return strdup ("<unknown>");
+ }
+
+- filename = table->files[file - 1].name;
++ filename = table->files[file].name;
++
+ if (filename == NULL)
+ return strdup ("<unknown>");
+
+@@ -1811,12 +1826,17 @@ concat_filename (struct line_info_table *table, unsigned int \
file)
+ char *name;
+ size_t len;
+
+- if (table->files[file - 1].dir
++ if (table->files[file].dir
+ /* PR 17512: file: 0317e960. */
+- && table->files[file - 1].dir <= table->num_dirs
++ && table->files[file].dir <= table->num_dirs
+ /* PR 17512: file: 7f3d2e4b. */
+ && table->dirs != NULL)
+- subdir_name = table->dirs[table->files[file - 1].dir - 1];
++ {
++ if (table->use_dir_and_file_0)
++ subdir_name = table->dirs[table->files[file].dir];
++ else
++ subdir_name = table->dirs[table->files[file].dir - 1];
++ }
+
+ if (!subdir_name || !IS_ABSOLUTE_PATH (subdir_name))
+ dir_name = table->comp_dir;
+@@ -1857,10 +1877,12 @@ concat_filename (struct line_info_table *table, unsigned int \
file)
+
+ /* Check whether [low1, high1) can be combined with [low2, high2),
+ i.e., they touch or overlap. */
+-static bool ranges_overlap (bfd_vma low1,
+- bfd_vma high1,
+- bfd_vma low2,
+- bfd_vma high2)
++
++static bool
++ranges_overlap (bfd_vma low1,
++ bfd_vma high1,
++ bfd_vma low2,
++ bfd_vma high2)
+ {
+ if (low1 == low2 || high1 == high2)
+ return true;
+@@ -1887,15 +1909,16 @@ static bool ranges_overlap (bfd_vma low1,
+ /* Insert an address range in the trie mapping addresses to compilation units.
+ Will return the new trie node (usually the same as is being sent in, but
+ in case of a leaf-to-interior conversion, or expansion of a leaf, it may be
+- different), or NULL on failure.
+- */
+-static struct trie_node *insert_arange_in_trie(bfd *abfd,
+- struct trie_node *trie,
+- bfd_vma trie_pc,
+- unsigned int trie_pc_bits,
+- struct comp_unit *unit,
+- bfd_vma low_pc,
+- bfd_vma high_pc)
++ different), or NULL on failure. */
++
++static struct trie_node *
++insert_arange_in_trie (bfd *abfd,
++ struct trie_node *trie,
++ bfd_vma trie_pc,
++ unsigned int trie_pc_bits,
++ struct comp_unit *unit,
++ bfd_vma low_pc,
++ bfd_vma high_pc)
+ {
+ bfd_vma clamped_low_pc, clamped_high_pc;
+ int ch, from_ch, to_ch;
+@@ -2031,7 +2054,6 @@ static struct trie_node *insert_arange_in_trie(bfd *abfd,
+ return trie;
+ }
+
+-
+ static bool
+ arange_add (struct comp_unit *unit, struct arange *first_arange,
+ struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc)
+@@ -2412,10 +2434,8 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte \
**bufp,
+ }
+ }
+
+- /* Skip the first "zero entry", which is the compilation dir/file. */
+- if (datai != 0)
+- if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+- return false;
++ if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
++ return false;
+ }
+
+ *bufp = buf;
+@@ -2592,6 +2612,7 @@ decode_line_info (struct comp_unit *unit)
+ if (!read_formatted_entries (unit, &line_ptr, line_end, table,
+ line_info_add_file_name))
+ goto fail;
++ table->use_dir_and_file_0 = true;
+ }
+ else
+ {
+@@ -2614,6 +2635,7 @@ decode_line_info (struct comp_unit *unit)
+ if (!line_info_add_file_name (table, cur_file, dir, xtime, size))
+ goto fail;
+ }
++ table->use_dir_and_file_0 = false;
+ }
+
+ /* Read the statement sequences until there's nothing left. */
+@@ -2622,7 +2644,7 @@ decode_line_info (struct comp_unit *unit)
+ /* State machine registers. */
+ bfd_vma address = 0;
+ unsigned char op_index = 0;
+- char * filename = table->num_files ? concat_filename (table, 1) : NULL;
++ char * filename = NULL;
+ unsigned int line = 1;
+ unsigned int column = 0;
+ unsigned int discriminator = 0;
+@@ -2637,6 +2659,14 @@ decode_line_info (struct comp_unit *unit)
+ bfd_vma low_pc = (bfd_vma) -1;
+ bfd_vma high_pc = 0;
+
++ if (table->num_files)
++ {
++ if (table->use_dir_and_file_0)
++ filename = concat_filename (table, 0);
++ else
++ filename = concat_filename (table, 1);
++ }
++
+ /* Decode the table. */
+ while (!end_sequence && line_ptr < line_end)
+ {
+diff --git a/ld/testsuite/ld-x86-64/pr27587.err b/ld/testsuite/ld-x86-64/pr27587.err
+index fa870790..807750ca 100644
+--- a/ld/testsuite/ld-x86-64/pr27587.err
++++ b/ld/testsuite/ld-x86-64/pr27587.err
+@@ -1,3 +1,3 @@
+ #...
+-.*pr27587.i:4: undefined reference to `stack_size'
++.*pr27587/<artificial>:4: undefined reference to `stack_size'
+ #...
diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch
new file mode 100644
index 0000000000..603824155b
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch
@@ -0,0 +1,33 @@
+From 20c75f063a999f9e849a77613a82b15de78ea45f Mon Sep 17 00:00:00 2001
+From: Nick Clifton <nickc@redhat.com><mailto:nickc@redhat.com>
+Date: Fri, 23 Dec 2022 13:02:04 +0000
+Subject: [PATCH] Fix illegal memory access parsing corrupt DWARF information.
+
+ PR 29936
+ * dwarf2.c (concat_filename): Fix check for a directory index off
+ the end of the directory table.
+
+Upstream-Status: Backport \
[https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09]
+CVE: CVE-2023-22608
+
+Signed-off-by: Yash Shinde \
<Yash.Shinde@windriver.com><mailto:Yash.Shinde@windriver.com>
+
+---
+ bfd/ChangeLog | 6 ++++++
+ bfd/dwarf2.c | 3 ++-
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
+index b7839ad6..8b07a24c 100644
+--- a/bfd/dwarf2.c
++++ b/bfd/dwarf2.c
+@@ -1828,7 +1828,8 @@ concat_filename (struct line_info_table *table, unsigned int \
file)
+
+ if (table->files[file].dir
+ /* PR 17512: file: 0317e960. */
+- && table->files[file].dir <= table->num_dirs
++ && table->files[file].dir
++ <= (table->use_dir_and_file_0 ? table->num_dirs - 1 : table->num_dirs)
+ /* PR 17512: file: 7f3d2e4b. */
+ && table->dirs != NULL)
+ {
--
# Randy MacLeod
# Wind River Linux
[Attachment #3 (text/html)]
<html xmlns:o="urn:schemas-microsoft-com:office:office" \
xmlns:w="urn:schemas-microsoft-com:office:word" \
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" \
xmlns="http://www.w3.org/TR/REC-html40"> <head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Mangal;
panose-1:2 4 5 3 5 2 3 3 2 2;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
font-size:10.0pt;
font-family:"Courier New";}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:"Courier New";}
p.msonormal0, li.msonormal0, div.msonormal0
{mso-style-name:msonormal;
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-IN" link="blue" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal">Yes, the actual fix is <i>0020-CVE-2023-22608-3.patch</i>. The \
other two files are the dependent patch files required for this patch to apply. If \
these are excluded, the build gives errors in <i>do_compile</i> task due to missing \
code dependencies.</p> <p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Regards,<br>
Yash<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="mso-element:para-border-div;border:none;border-top:solid #E1E1E1 \
1.0pt;padding:3.0pt 0cm 0cm 0cm"> <p class="MsoNormal" \
style="border:none;padding:0cm"><b>From: </b><a \
href="mailto:Randy.MacLeod@windriver.com">MacLeod, Randy</a><br> <b>Sent: </b>28 \
February 2023 07:30<br> <b>To: </b><a href="mailto:yashinde145@gmail.com">Yash \
Shinde</a>; <a href="mailto:openembedded-core@lists.openembedded.org"> \
openembedded-core@lists.openembedded.org</a>; <a href="mailto:steve@sakoman.com"> \
steve@sakoman.com</a><br> <b>Cc: </b><a \
href="mailto:Umesh.Kallapa@windriver.com">Kallapa, Umesh</a>; <a \
href="mailto:Naveen.Gowda@windriver.com"> Gowda, Naveen</a>; <a \
href="mailto:Sundeep.Kokkonda@windriver.com">Kokkonda, Sundeep</a>; <a \
href="mailto:Shivaprasad.Moodalappa@windriver.com">Moodalappa, Shivaprasad</a>; <a \
href="mailto:Yash.Shinde@windriver.com">Shinde, Yash</a><br> <b>Subject: </b>Re: \
[kirkstone][PATCH] binutils : Fix CVE-2023-22608</p> </div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">On 2023-02-26 04:11, Yash Shinde wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre>From: Yash Shinde <a \
href="mailto:Yash.Shinde@windriver.com"><Yash.Shinde@windriver.com></a></pre> \
<pre><o:p> </o:p></pre> <pre>Upstream-Status: Backport [<a \
href="https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009 \
bc9b243cd4dfa10ae1ac09">https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09</a>]</pre>
<pre><o:p> </o:p></pre>
<pre>Signed-off-by: Yash Shinde <a \
href="mailto:Yash.Shinde@windriver.com"><Yash.Shinde@windriver.com></a></pre> \
<pre>---</pre> <pre> \
.../binutils/binutils-2.38.inc \
| 3 +</pre> <pre> \
.../binutils/0020-CVE-2023-22608-1.patch | 502 \
++++++++++++++++++</pre> <pre> \
.../binutils/0020-CVE-2023-22608-2.patch | 211 \
++++++++</pre> <pre> \
.../binutils/0020-CVE-2023-22608-3.patch | 33 \
++</pre> </blockquote>
<pre>This is a large patch so I took a look at it.</pre>
<pre><o:p> </o:p></pre>
<pre><o:p> </o:p></pre>
<pre>The actual fix is: 0020-CVE-2023-22608-3.patch</pre>
<p><a href="https://sourceware.org/git/?p=binutils-gdb.git;a=blobdiff;f=bfd/dwarf2.c;h \
=88335cb4fb0dddc3b1ca8a1d76c32b88ff85aa89;hp=b608afbc0cf260e98e2f87ab6d55c935937b2810; \
hb=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09;hpb=8fbad19958c9b9c06a710bf7d6589d52f1ed8a \
64">https://sourceware.org/git/?p=binutils-gdb.git;a=blobdiff;f=bfd/dwarf2.c;h=88335cb \
4fb0dddc3b1ca8a1d76c32b88ff85aa89;hp=b608afbc0cf260e98e2f87ab6d55c935937b2810;hb=8af23 \
b30edbaedf009bc9b243cd4dfa10ae1ac09;hpb=8fbad19958c9b9c06a710bf7d6589d52f1ed8a64</a></p>
<p>which is just a few lines.</p>
<p>Unfortunately we do need the other two, rather large patches to make that apply it \
seems.</p> <p>The patch that adds a trie seems like a feature but the code is all (I \
think) file<br> scope local structs with static functions so as far as the ABI \
stability, it seems fine<br> to backport. It will change the memory footprint:<br>
<br>
commit b43771b045fb5616da3964f2994eefbe8ae70d32<br>
Author: Steinar H. Gunderson <a \
href="mailto:sesse@google.com"><sesse@google.com></a><br> Date: Fri \
May 20 10:10:34 2022<br> <br>
add a trie to map quickly from address range to compilation \
unit<br> <br>
When using perf to profile large binaries, \
_bfd_dwarf2_find_nearest_line()<br> becomes a hotspot, as perf \
wants to get line number information<br> (for inline-detection \
purposes) for each and every sample. In Chromium<br> in particular \
(the content_shell binary), this entails going through<br> 475k \
address ranges, which takes a long time when done repeatedly.<br> \
<br> Add a radix-256 trie over the address space to quickly \
map address to<br> compilation unit spaces; for content_shell, \
which is 1.6 GB when some<br> (but not full) debug information \
turned is on, we go from 6 ms to<br> 0.006 ms (6 µs) for each \
lookup from address to compilation unit, a 1000x<br> speedup.<br>
<br>
There is a modest RAM increase of 180 MB in this binary (the \
existing<br> linked list over ranges uses about 10 MB, and the \
entire perf job uses<br> between 2–3 GB for a medium-size \
profile); for smaller binaries with few<br> ranges, there should \
be hardly any extra RAM usage at all.<br> <br>
../Randy</p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre><o:p> </o:p></pre>
<pre> 4 files changed, 749 insertions(+)</pre>
<pre> create mode 100644 \
meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch</pre> <pre> \
create mode 100644 meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch</pre>
<pre> create mode 100644 \
meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch</pre> \
<pre><o:p> </o:p></pre> <pre>diff --git \
a/meta/recipes-devtools/binutils/binutils-2.38.inc \
b/meta/recipes-devtools/binutils/binutils-2.38.inc</pre> <pre>index \
0a4a0d7bc1..30a34d7ba4 100644</pre> <pre>--- \
a/meta/recipes-devtools/binutils/binutils-2.38.inc</pre> <pre>+++ \
b/meta/recipes-devtools/binutils/binutils-2.38.inc</pre> <pre>@@ -43,5 +43,8 @@ \
SRC_URI = "\</pre> <pre> <a \
href="file://0018-CVE-2022-38128-2.patch">file://0018-CVE-2022-38128-2.patch</a> \
\</pre> <pre> <a \
href="file://0018-CVE-2022-38128-3.patch">file://0018-CVE-2022-38128-3.patch</a> \
\</pre> <pre> <a \
href="file://0019-CVE-2022-4285.patch">file://0019-CVE-2022-4285.patch</a> \</pre> \
<pre>+ <a \
href="file://0020-CVE-2023-22608-1.patch">file://0020-CVE-2023-22608-1.patch</a> \
\</pre> <pre>+ <a \
href="file://0020-CVE-2023-22608-2.patch">file://0020-CVE-2023-22608-2.patch</a> \
\</pre> <pre>+ <a \
href="file://0020-CVE-2023-22608-3.patch">file://0020-CVE-2023-22608-3.patch</a> \
\</pre> <pre> "</pre>
<pre> S = "${WORKDIR}/git"</pre>
<pre>diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch</pre> <pre>new \
file mode 100644</pre> <pre>index 0000000000..dd3d533d0d</pre>
<pre>--- /dev/null</pre>
<pre>+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-1.patch</pre>
<pre>@@ -0,0 +1,502 @@</pre>
<pre>+From a79c274dad99863f58b9ed627b38908daadb6d7e Mon Sep 17 00:00:00 2001</pre>
<pre>+From: "Steinar H. Gunderson" <a \
href="mailto:sesse@google.com"><sesse@google.com></a></pre> <pre>+Date: Fri, 20 \
May 2022 16:10:34 +0200</pre> <pre>+Subject: [PATCH] add a trie to map quickly from \
address range to compilation</pre> <pre>+ unit</pre>
<pre>+MIME-Version: 1.0</pre>
<pre>+Content-Type: text/plain; charset=UTF-8</pre>
<pre>+Content-Transfer-Encoding: 8bit</pre>
<pre>+</pre>
<pre>+When using perf to profile large binaries, \
_bfd_dwarf2_find_nearest_line()</pre> <pre>+becomes a hotspot, as perf wants to get \
line number information</pre> <pre>+(for inline-detection purposes) for each and \
every sample. In Chromium</pre> <pre>+in particular (the content_shell binary), this \
entails going through</pre> <pre>+475k address ranges, which takes a long time when \
done repeatedly.</pre> <pre>+</pre>
<pre>+Add a radix-256 trie over the address space to quickly map address to</pre>
<pre>+compilation unit spaces; for content_shell, which is 1.6 GB when some</pre>
<pre>+(but not full) debug information turned is on, we go from 6 ms to</pre>
<pre>+0.006 ms (6 µs) for each lookup from address to compilation unit, a 1000x</pre>
<pre>+speedup.</pre>
<pre>+</pre>
<pre>+There is a modest RAM increase of 180 MB in this binary (the existing</pre>
<pre>+linked list over ranges uses about 10 MB, and the entire perf job uses</pre>
<pre>+between 2-3 GB for a medium-size profile); for smaller binaries with few</pre>
<pre>+ranges, there should be hardly any extra RAM usage at all.</pre>
<pre>+</pre>
<pre>+Upstream-Status: Backport [<a \
href="https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=b43771b045fb5616da \
3964f2994eefbe8ae70d32">https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=b43771b045fb5616da3964f2994eefbe8ae70d32</a>]</pre>
<pre>+</pre>
<pre>+CVE: CVE-2023-22608</pre>
<pre>+</pre>
<pre>+Signed-off-by: Yash Shinde <a \
href="mailto:Yash.Shinde@windriver.com"><Yash.Shinde@windriver.com></a></pre> \
<pre>+</pre> <pre>+---</pre>
<pre>+ bfd/dwarf2.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++---</pre>
<pre>+ 1 file changed, 312 insertions(+), 14 deletions(-)</pre>
<pre>+</pre>
<pre>+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c</pre>
<pre>+index fdf071c3..0ae50a37 100644</pre>
<pre>+--- a/bfd/dwarf2.c</pre>
<pre>++++ b/bfd/dwarf2.c</pre>
<pre>+@@ -82,6 +82,77 @@ struct adjusted_section</pre>
<pre>+ bfd_vma adj_vma;</pre>
<pre>+ };</pre>
<pre>+</pre>
<pre>++/* A trie to map quickly from address range to compilation unit.</pre>
<pre>++</pre>
<pre>++ This is a fairly standard radix-256 trie, used to quickly locate \
which</pre> <pre>++ compilation unit any given address belongs to. \
Given that each compilation</pre> <pre>++ unit may register hundreds of \
very small and unaligned ranges (which may</pre> <pre>++ potentially \
overlap, due to inlining and other concerns), and a large</pre> <pre>++ \
program may end up containing hundreds of thousands of such ranges, we cannot</pre> \
<pre>++ scan through them linearly without undue slowdown.</pre> \
<pre>++</pre> <pre>++ We use a hybrid trie to avoid memory explosion: \
There are two types of trie</pre> <pre>++ nodes, leaves and interior \
nodes. (Almost all nodes are leaves, so they</pre> <pre>++ take up \
the bulk of the memory usage.) Leaves contain a simple array of</pre> \
<pre>++ ranges (high/low address) and which compilation unit contains \
those ranges,</pre> <pre>++ and when we get to a leaf, we scan through it \
linearly. Interior nodes</pre> <pre>++ contain pointers to 256 \
other nodes, keyed by the next byte of the address.</pre> <pre>++ So for \
a 64-bit address like 0x1234567abcd, we would start at the root and go</pre> \
<pre>++ down \
child[0x00]->child[0x00]->child[0x01]->child[0x23]->child[0x45] \
etc.,</pre> <pre>++ until we hit a leaf. (Nodes are, in general, \
leaves until they exceed the</pre> <pre>++ default allocation of 16 \
elements, at which point they are converted to</pre> <pre>++ interior \
node if possible.) This gives us near-constant lookup times;</pre> \
<pre>++ the only thing that can be costly is if there are lots of \
overlapping ranges</pre> <pre>++ within a single 256-byte segment of the \
binary, in which case we have to</pre> <pre>++ scan through them all to \
find the best match.</pre> <pre>++</pre>
<pre>++ For a binary with few ranges, we will in practice only have a \
single leaf</pre> <pre>++ node at the root, containing a simple \
array. Thus, the scheme is efficient</pre> <pre>++ for both small \
and large binaries.</pre> <pre>++ */</pre>
<pre>++</pre>
<pre>++/* Experiments have shown 16 to be a memory-efficient default leaf size.</pre>
<pre>++ The only case where a leaf will hold more memory than this, is at \
the</pre> <pre>++ bottomost level (covering 256 bytes in the binary), \
where we'll expand</pre> <pre>++ the leaf to be able to hold more ranges \
if needed.</pre> <pre>++ */</pre>
<pre>++#define TRIE_LEAF_SIZE 16</pre>
<pre>++</pre>
<pre>++/* All trie_node pointers will really be trie_leaf or trie_interior,</pre>
<pre>++ but they have this common head. */</pre>
<pre>++struct trie_node</pre>
<pre>++{</pre>
<pre>++ /* If zero, we are an interior node.</pre>
<pre>++ Otherwise, how many ranges we have room for in this \
leaf. */</pre> <pre>++ unsigned int num_room_in_leaf;</pre>
<pre>++};</pre>
<pre>++</pre>
<pre>++struct trie_leaf</pre>
<pre>++{</pre>
<pre>++ struct trie_node head;</pre>
<pre>++ unsigned int num_stored_in_leaf;</pre>
<pre>++ struct {</pre>
<pre>++ struct comp_unit *unit;</pre>
<pre>++ bfd_vma low_pc, high_pc;</pre>
<pre>++ } ranges[TRIE_LEAF_SIZE];</pre>
<pre>++};</pre>
<pre>++</pre>
<pre>++struct trie_interior</pre>
<pre>++{</pre>
<pre>++ struct trie_node head;</pre>
<pre>++ struct trie_node *children[256];</pre>
<pre>++};</pre>
<pre>++</pre>
<pre>++static struct trie_node *alloc_trie_leaf (bfd *abfd)</pre>
<pre>++{</pre>
<pre>++ struct trie_leaf *leaf =</pre>
<pre>++ bfd_zalloc (abfd, sizeof (struct trie_leaf));</pre>
<pre>++ if (leaf == NULL)</pre>
<pre>++ return NULL;</pre>
<pre>++ leaf->head.num_room_in_leaf = TRIE_LEAF_SIZE;</pre>
<pre>++ return &leaf->head;</pre>
<pre>++}</pre>
<pre>++</pre>
<pre>+ struct dwarf2_debug_file</pre>
<pre>+ {</pre>
<pre>+ /* The actual bfd from which debug info was loaded. Might \
be</pre> <pre>+@@ -139,6 +210,9 @@ struct dwarf2_debug_file</pre>
<pre>+ /* A list of all previously read comp_units. */</pre>
<pre>+ struct comp_unit *all_comp_units;</pre>
<pre>+</pre>
<pre>++ /* A list of all previously read comp_units with no ranges (yet). \
*/</pre> <pre>++ struct comp_unit *all_comp_units_without_ranges;</pre>
<pre>++</pre>
<pre>+ /* Last comp unit in list above. */</pre>
<pre>+ struct comp_unit *last_comp_unit;</pre>
<pre>+</pre>
<pre>+@@ -147,6 +221,9 @@ struct dwarf2_debug_file</pre>
<pre>+</pre>
<pre>+ /* Hash table to map offsets to decoded abbrevs. */</pre>
<pre>+ htab_t abbrev_offsets;</pre>
<pre>++</pre>
<pre>++ /* Root of a trie to map addresses to compilation units. */</pre>
<pre>++ struct trie_node *trie_root;</pre>
<pre>+ };</pre>
<pre>+</pre>
<pre>+ struct dwarf2_debug</pre>
<pre>+@@ -220,6 +297,11 @@ struct comp_unit</pre>
<pre>+ /* Chain the previously read compilation units. */</pre>
<pre>+ struct comp_unit *next_unit;</pre>
<pre>+</pre>
<pre>++ /* Chain the previously read compilation units that have no ranges \
yet.</pre> <pre>++ We scan these separately when we have a \
trie over the ranges.</pre> <pre>++ Unused if arange.high != \
0. */</pre> <pre>++ struct comp_unit *next_unit_without_ranges;</pre>
<pre>++</pre>
<pre>+ /* Likewise, chain the compilation unit read after this one.</pre>
<pre>+ The comp units are stored in reversed reading \
order. */</pre> <pre>+ struct comp_unit *prev_unit;</pre>
<pre>+@@ -296,6 +378,10 @@ struct comp_unit</pre>
<pre>+</pre>
<pre>+ /* TRUE if symbols are cached in hash table for faster lookup by \
name. */</pre> <pre>+ bool cached;</pre>
<pre>++</pre>
<pre>++ /* Used when iterating over trie leaves to know which units we \
have</pre> <pre>++ already seen in this iteration. \
*/</pre> <pre>++ bool mark;</pre>
<pre>+ };</pre>
<pre>+</pre>
<pre>+ /* This data structure holds the information of an abbrev. */</pre>
<pre>+@@ -1766,9 +1852,189 @@ concat_filename (struct line_info_table *table, \
unsigned int file)</pre> <pre>+ return strdup (filename);</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>++/* Number of bits in a bfd_vma. */</pre>
<pre>++#define VMA_BITS (8 * sizeof (bfd_vma))</pre>
<pre>++</pre>
<pre>++/* Check whether [low1, high1) can be combined with [low2, high2),</pre>
<pre>++ i.e., they touch or overlap. */</pre>
<pre>++static bool ranges_overlap (bfd_vma low1,</pre>
<pre>++ \
bfd_vma high1,</pre> \
<pre>++ \
bfd_vma low2,</pre> \
<pre>++ \
bfd_vma high2)</pre> <pre>++{</pre>
<pre>++ if (low1 == low2 || high1 == high2)</pre>
<pre>++ return true;</pre>
<pre>++</pre>
<pre>++ /* Sort so that low1 is below low2. */</pre>
<pre>++ if (low1 > low2)</pre>
<pre>++ {</pre>
<pre>++ bfd_vma tmp;</pre>
<pre>++</pre>
<pre>++ tmp = low1;</pre>
<pre>++ low1 = low2;</pre>
<pre>++ low2 = tmp;</pre>
<pre>++</pre>
<pre>++ tmp = high1;</pre>
<pre>++ high1 = high2;</pre>
<pre>++ high2 = tmp;</pre>
<pre>++ }</pre>
<pre>++</pre>
<pre>++ /* We touch iff low2 == high1.</pre>
<pre>++ We overlap iff low2 is within [low1, high1). */</pre>
<pre>++ return (low2 <= high1);</pre>
<pre>++}</pre>
<pre>++</pre>
<pre>++/* Insert an address range in the trie mapping addresses to compilation \
units.</pre> <pre>++ Will return the new trie node (usually the same as \
is being sent in, but</pre> <pre>++ in case of a leaf-to-interior \
conversion, or expansion of a leaf, it may be</pre> <pre>++ different), \
or NULL on failure.</pre> <pre>++ */</pre>
<pre>++static struct trie_node *insert_arange_in_trie(bfd *abfd,</pre>
<pre>++ \
struct trie_node *trie,</pre> \
<pre>++ \
bfd_vma trie_pc,</pre> \
<pre>++ \
unsigned int trie_pc_bits,</pre> \
<pre>++ \
struct comp_unit *unit,</pre> \
<pre>++ \
bfd_vma low_pc,</pre> \
<pre>++ \
bfd_vma high_pc)</pre> <pre>++{</pre>
<pre>++ bfd_vma clamped_low_pc, clamped_high_pc;</pre>
<pre>++ int ch, from_ch, to_ch;</pre>
<pre>++ bool is_full_leaf = false;</pre>
<pre>++</pre>
<pre>++ /* See if we can extend any of the existing ranges. This \
merging</pre> <pre>++ isn't perfect (if merging opens up the \
possibility of merging two existing</pre> <pre>++ ranges, we \
won't find them), but it takes the majority of the cases. */</pre> \
<pre>++ if (trie->num_room_in_leaf > 0)</pre> <pre>++ \
{</pre> <pre>++ struct trie_leaf *leaf = (struct \
trie_leaf *) trie;</pre> <pre>++ unsigned int i;</pre>
<pre>++</pre>
<pre>++ for (i = 0; i < leaf->num_stored_in_leaf; \
++i)</pre> <pre>++ {</pre>
<pre>++ if (leaf->ranges[i].unit == \
unit &&</pre> <pre>++ \
ranges_overlap(low_pc, high_pc,</pre> \
<pre>++ \
leaf->ranges[i].low_pc, \
leaf->ranges[i].high_pc))</pre> <pre>++ \
{</pre> <pre>++ \
if (low_pc < leaf->ranges[i].low_pc)</pre> \
<pre>++ \
leaf->ranges[i].low_pc = low_pc;</pre> <pre>++ \
if (high_pc > leaf->ranges[i].high_pc)</pre> \
<pre>++ \
leaf->ranges[i].high_pc = high_pc;</pre> \
<pre>++ return \
trie;</pre> <pre>++ }</pre>
<pre>++ }</pre>
<pre>++</pre>
<pre>++ is_full_leaf = leaf->num_stored_in_leaf == \
trie->num_room_in_leaf;</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>++ /* If we're a leaf with no more room and we're _not_ at the \
bottom,</pre> <pre>++ convert to an interior node. \
*/</pre> <pre>++ if (is_full_leaf && trie_pc_bits < VMA_BITS)</pre>
<pre>++ {</pre>
<pre>++ const struct trie_leaf *leaf = (struct \
trie_leaf *) trie;</pre> <pre>++ unsigned int i;</pre>
<pre>++</pre>
<pre>++ trie = bfd_zalloc (abfd, sizeof (struct \
trie_interior));</pre> <pre>++ if (!trie)</pre>
<pre>++ return NULL;</pre>
<pre>++ is_full_leaf = false;</pre>
<pre>++</pre>
<pre>++ /* TODO: If we wanted to save a little more \
memory at the cost of</pre> <pre>++ complexity, \
we could have reused the old leaf node as one of the</pre> \
<pre>++ children of the new interior node, \
instead of throwing it away. */</pre> <pre>++ for \
(i = 0; i < leaf->num_stored_in_leaf; ++i)</pre> \
<pre>++ {</pre> \
<pre>++ if (!insert_arange_in_trie (abfd, \
trie, trie_pc, trie_pc_bits,</pre> \
<pre>++ \
leaf->ranges[i].unit, \
leaf->ranges[i].low_pc,</pre> \
<pre>++ \
leaf->ranges[i].high_pc))</pre> \
<pre>++ return NULL;</pre> \
<pre>++ }</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>++ /* If we're a leaf with no more room and we _are_ at the bottom,</pre>
<pre>++ we have no choice but to just make it larger. \
*/</pre> <pre>++ if (is_full_leaf)</pre>
<pre>++ {</pre>
<pre>++ const struct trie_leaf *leaf = (struct \
trie_leaf *) trie;</pre> <pre>++ unsigned int \
new_room_in_leaf = trie->num_room_in_leaf * 2;</pre> \
<pre>++ struct trie_leaf *new_leaf;</pre> <pre>++</pre>
<pre>++ new_leaf = bfd_zalloc (abfd,</pre>
<pre>++ sizeof (struct trie_leaf) +</pre>
<pre>++ (new_room_in_leaf - \
TRIE_LEAF_SIZE) * sizeof (leaf->ranges[0]));</pre> \
<pre>++ new_leaf->head.num_room_in_leaf = \
new_room_in_leaf;</pre> <pre>++ \
new_leaf->num_stored_in_leaf = leaf->num_stored_in_leaf;</pre> <pre>++</pre>
<pre>++ memcpy (new_leaf->ranges,</pre>
<pre>++ \
leaf->ranges,</pre> <pre>++ \
leaf->num_stored_in_leaf * sizeof \
(leaf->ranges[0]));</pre> <pre>++ trie = \
&new_leaf->head;</pre> <pre>++ is_full_leaf = \
false;</pre> <pre>++</pre>
<pre>++ /* Now the insert below will go through. \
*/</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>++ /* If we're a leaf (now with room), we can just insert at the \
end. */</pre> <pre>++ if (trie->num_room_in_leaf > 0)</pre>
<pre>++ {</pre>
<pre>++ struct trie_leaf *leaf = (struct trie_leaf *) \
trie;</pre> <pre>++</pre>
<pre>++ unsigned int i = \
leaf->num_stored_in_leaf++;</pre> <pre>++ \
leaf->ranges[i].unit = unit;</pre> <pre>++ \
leaf->ranges[i].low_pc = low_pc;</pre> <pre>++ \
leaf->ranges[i].high_pc = high_pc;</pre> <pre>++ \
return trie;</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>++ /* Now we are definitely an interior node, so recurse into all</pre>
<pre>++ the relevant buckets. */</pre>
<pre>++</pre>
<pre>++ /* Clamp the range to the current trie bucket. */</pre>
<pre>++ clamped_low_pc = low_pc;</pre>
<pre>++ clamped_high_pc = high_pc;</pre>
<pre>++ if (trie_pc_bits > 0)</pre>
<pre>++ {</pre>
<pre>++ bfd_vma bucket_high_pc =</pre>
<pre>++ trie_pc + ((bfd_vma)-1 >> \
trie_pc_bits); /* Inclusive. */</pre> \
<pre>++ if (clamped_low_pc < trie_pc)</pre> \
<pre>++ clamped_low_pc = trie_pc;</pre> \
<pre>++ if (clamped_high_pc > bucket_high_pc)</pre> \
<pre>++ clamped_high_pc = bucket_high_pc;</pre> \
<pre>++ }</pre> <pre>++</pre>
<pre>++ /* Insert the ranges in all buckets that it spans. */</pre>
<pre>++ from_ch = (clamped_low_pc >> (VMA_BITS - trie_pc_bits - 8)) & \
0xff;</pre> <pre>++ to_ch = ((clamped_high_pc - 1) >> (VMA_BITS - \
trie_pc_bits - 8)) & 0xff;</pre> <pre>++ for (ch = from_ch; ch <= to_ch; \
++ch)</pre> <pre>++ {</pre>
<pre>++ struct trie_interior *interior = (struct \
trie_interior *) trie;</pre> <pre>++ struct trie_node \
*child = interior->children[ch];</pre> <pre>++</pre>
<pre>++ if (child == NULL)</pre>
<pre>++ {</pre>
<pre>++ child = alloc_trie_leaf \
(abfd);</pre> <pre>++ if (!child)</pre>
<pre>++ return NULL;</pre>
<pre>++ }</pre>
<pre>++ child = insert_arange_in_trie (abfd,</pre>
<pre>++ \
child,</pre> \
<pre>++ \
trie_pc + ((bfd_vma)ch << (VMA_BITS - trie_pc_bits - \
8)),</pre> <pre>++ \
trie_pc_bits + 8,</pre> \
<pre>++ \
unit,</pre> \
<pre>++ \
low_pc,</pre> \
<pre>++ \
high_pc);</pre> <pre>++ if \
(!child)</pre> <pre>++ return NULL;</pre>
<pre>++</pre>
<pre>++ interior->children[ch] = child;</pre>
<pre>++ }</pre>
<pre>++</pre>
<pre>++ return trie;</pre>
<pre>++}</pre>
<pre>++</pre>
<pre>++</pre>
<pre>+ static bool</pre>
<pre>+-arange_add (const struct comp_unit *unit, struct arange *first_arange,</pre>
<pre>+- bfd_vma low_pc, \
bfd_vma high_pc)</pre> <pre>++arange_add (struct comp_unit *unit, struct arange \
*first_arange,</pre> <pre>++ \
struct trie_node **trie_root, bfd_vma low_pc, bfd_vma high_pc)</pre> <pre>+ {</pre>
<pre>+ struct arange *arange;</pre>
<pre>+</pre>
<pre>+@@ -1776,6 +2042,19 @@ arange_add (const struct comp_unit *unit, struct arange \
*first_arange,</pre> <pre>+ if (low_pc == high_pc)</pre>
<pre>+ return true;</pre>
<pre>+</pre>
<pre>++ if (trie_root != NULL)</pre>
<pre>++ {</pre>
<pre>++ *trie_root = insert_arange_in_trie \
(unit->file->bfd_ptr,</pre> \
<pre>++ \
*trie_root,</pre> \
<pre>++ \
0,</pre> <pre>++ &nb \
sp; \
0,</pre> <pre>++ &nb \
sp; \
unit,</pre> <pre>++ \
\
low_pc,</pre> \
<pre>++ \
high_pc);</pre> <pre>++ if (*trie_root == \
NULL)</pre> <pre>++ return false;</pre>
<pre>++ }</pre>
<pre>++</pre>
<pre>+ /* If the first arange is empty, use it. */</pre>
<pre>+ if (first_arange->high == 0)</pre>
<pre>+ {</pre>
<pre>+@@ -2410,7 +2689,8 @@ decode_line_info (struct comp_unit *unit)</pre>
<pre>+ low_pc = \
address;</pre> <pre>+ if (address \
> high_pc)</pre> <pre>+ \
high_pc = address;</pre> \
<pre>+- \
if (!arange_add (unit, &unit->arange, low_pc, high_pc))</pre> \
<pre>++ \
if (!arange_add (unit, &unit->arange, \
&unit->file->trie_root,</pre> \
<pre>++ \
low_pc, high_pc))</pre> <pre>+ \
goto line_fail;</pre> \
<pre>+ break;</pre> \
<pre>+ case DW_LNE_set_address:</pre> \
<pre>+@@ -3134,7 +3414,7 @@ find_abstract_instance (struct comp_unit *unit,</pre> \
<pre>+</pre> <pre>+ static bool</pre>
<pre>+ read_ranges (struct comp_unit *unit, struct arange *arange,</pre>
<pre>+- bfd_uint64_t \
offset)</pre> <pre>++ \
struct trie_node **trie_root, bfd_uint64_t offset)</pre> <pre>+ {</pre>
<pre>+ bfd_byte *ranges_ptr;</pre>
<pre>+ bfd_byte *ranges_end;</pre>
<pre>+@@ -3169,7 +3449,7 @@ read_ranges (struct comp_unit *unit, struct arange \
*arange,</pre> <pre>+ base_address = high_pc;</pre>
<pre>+ else</pre>
<pre>+ {</pre>
<pre>+- if (!arange_add (unit, \
arange,</pre> <pre>++ if (!arange_add \
(unit, arange, trie_root,</pre> \
<pre>+ \
base_address + low_pc, base_address + high_pc))</pre> <pre>+ \
return false;</pre> <pre>+ }</pre>
<pre>+@@ -3179,7 +3459,7 @@ read_ranges (struct comp_unit *unit, struct arange \
*arange,</pre> <pre>+</pre>
<pre>+ static bool</pre>
<pre>+ read_rnglists (struct comp_unit *unit, struct arange *arange,</pre>
<pre>+- \
bfd_uint64_t offset)</pre> <pre>++ \
struct trie_node **trie_root, bfd_uint64_t \
offset)</pre> <pre>+ {</pre>
<pre>+ bfd_byte *rngs_ptr;</pre>
<pre>+ bfd_byte *rngs_end;</pre>
<pre>+@@ -3253,19 +3533,19 @@ read_rnglists (struct comp_unit *unit, struct arange \
*arange,</pre> <pre>+ return false;</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>+- if (!arange_add (unit, arange, low_pc, \
high_pc))</pre> <pre>++ if (!arange_add (unit, arange, \
trie_root, low_pc, high_pc))</pre> <pre>+ return false;</pre>
<pre>+ }</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>+ static bool</pre>
<pre>+ read_rangelist (struct comp_unit *unit, struct arange *arange,</pre>
<pre>+- \
bfd_uint64_t offset)</pre> \
<pre>++ \
struct trie_node **trie_root, bfd_uint64_t offset)</pre> <pre>+ {</pre>
<pre>+ if (unit->version <= 4)</pre>
<pre>+- return read_ranges (unit, arange, offset);</pre>
<pre>++ return read_ranges (unit, arange, trie_root, offset);</pre>
<pre>+ else</pre>
<pre>+- return read_rnglists (unit, arange, offset);</pre>
<pre>++ return read_rnglists (unit, arange, trie_root, \
offset);</pre> <pre>+ }</pre>
<pre>+</pre>
<pre>+ static struct funcinfo *</pre>
<pre>+@@ -3563,7 +3843,8 @@ scan_unit_for_symbols (struct comp_unit *unit)</pre>
<pre>+</pre>
<pre>+ case DW_AT_ranges:</pre>
<pre>+ if (is_int_form \
(&attr)</pre> <pre>+- \
&& !read_rangelist (unit, \
&func->arange, attr.u.val))</pre> \
<pre>++ \
&& !read_rangelist (unit, \
&func->arange,</pre> \
<pre>++ \
&unit->file->trie_root, attr.u.val))</pre> \
<pre>+ goto fail;</pre> \
<pre>+ break;</pre> <pre>+</pre>
<pre>+@@ -3679,7 +3960,8 @@ scan_unit_for_symbols (struct comp_unit *unit)</pre>
<pre>+</pre>
<pre>+ if (func && high_pc != 0)</pre>
<pre>+ {</pre>
<pre>+- if (!arange_add (unit, \
&func->arange, low_pc, high_pc))</pre> \
<pre>++ if (!arange_add (unit, \
&func->arange, &unit->file->trie_root,</pre> \
<pre>++ \
low_pc, high_pc))</pre> <pre>+ goto fail;</pre>
<pre>+ }</pre>
<pre>+ }</pre>
<pre>+@@ -3874,7 +4156,8 @@ parse_comp_unit (struct dwarf2_debug *stash,</pre>
<pre>+</pre>
<pre>+ case DW_AT_ranges:</pre>
<pre>+ if (is_int_form (&attr)</pre>
<pre>+- && \
!read_rangelist (unit, &unit->arange, attr.u.val))</pre> \
<pre>++ && \
!read_rangelist (unit, &unit->arange,</pre> \
<pre>++ \
&unit->file->trie_root, attr.u.val))</pre> <pre>+ \
return NULL;</pre> <pre>+ break;</pre>
<pre>+</pre>
<pre>+@@ -3916,7 +4199,8 @@ parse_comp_unit (struct dwarf2_debug *stash,</pre>
<pre>+ high_pc += low_pc;</pre>
<pre>+ if (high_pc != 0)</pre>
<pre>+ {</pre>
<pre>+- if (!arange_add (unit, &unit->arange, \
low_pc, high_pc))</pre> <pre>++ if (!arange_add (unit, \
&unit->arange, &unit->file->trie_root,</pre> \
<pre>++ \
low_pc, high_pc))</pre> <pre>+ return \
NULL;</pre> <pre>+ }</pre>
<pre>+</pre>
<pre>+@@ -4747,6 +5031,14 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd \
*debug_bfd,</pre> <pre>+ if (!stash->alt.abbrev_offsets)</pre>
<pre>+ return false;</pre>
<pre>+</pre>
<pre>++ stash->f.trie_root = alloc_trie_leaf (abfd);</pre>
<pre>++ if (!stash->f.trie_root)</pre>
<pre>++ return false;</pre>
<pre>++</pre>
<pre>++ stash->alt.trie_root = alloc_trie_leaf (abfd);</pre>
<pre>++ if (!stash->alt.trie_root)</pre>
<pre>++ return false;</pre>
<pre>++</pre>
<pre>+ *pinfo = stash;</pre>
<pre>+</pre>
<pre>+ if (debug_bfd == NULL)</pre>
<pre>+@@ -4918,6 +5210,12 @@ stash_comp_unit (struct dwarf2_debug *stash, struct \
dwarf2_debug_file *file)</pre> <pre>+ each->next_unit = \
file->all_comp_units;</pre> <pre>+ file->all_comp_units = each;</pre>
<pre>+</pre>
<pre>++ if (each->arange.high == \
0)</pre> <pre>++ {</pre>
<pre>++ \
each->next_unit_without_ranges = file->all_comp_units_without_ranges;</pre> \
<pre>++ \
file->all_comp_units_without_ranges = each->next_unit_without_ranges;</pre> \
<pre>++ }</pre> <pre>++</pre>
<pre>+ file->info_ptr += length;</pre>
<pre>+ return each;</pre>
<pre>+ }</pre>
<pre>diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch</pre> <pre>new \
file mode 100644</pre> <pre>index 0000000000..8ffb500c1d</pre>
<pre>--- /dev/null</pre>
<pre>+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-2.patch</pre>
<pre>@@ -0,0 +1,211 @@</pre>
<pre>+From 73e97e32e1428d63d81d971176772ae69397a1a0 Mon Sep 17 00:00:00 2001</pre>
<pre>+From: Nick Clifton <a \
href="mailto:nickc@redhat.com"><nickc@redhat.com></a></pre> <pre>+Date: Tue, 30 \
Aug 2022 16:01:20 +0100</pre> <pre>+Subject: [PATCH] BFD library: Use entry 0 in \
directory and filename tables of</pre> <pre>+ DWARF-5 debug info.</pre>
<pre>+</pre>
<pre>+ PR 29529</pre>
<pre>+ * dwarf2.c (struct line_info_table): Add new field:</pre>
<pre>+ use_dir_and_file_0.</pre>
<pre>+ (concat_filename): Use new field to help select the correct table</pre>
<pre>+ slot.</pre>
<pre>+ (read_formatted_entries): Do not skip entry 0.</pre>
<pre>+ (decode_line_info): Set new field depending upon the version of</pre>
<pre>+ DWARF being parsed. Initialise filename based upon the setting of</pre>
<pre>+ the new field.</pre>
<pre>+</pre>
<pre>+Upstream-Status: Backport [<a \
href="https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=37833b966576c5d25e \
797ea3b6c33d0459a71892">https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=37833b966576c5d25e797ea3b6c33d0459a71892</a>]</pre>
<pre>+CVE: CVE-2023-22608</pre>
<pre>+</pre>
<pre>+Signed-off-by: Yash Shinde <a \
href="mailto:Yash.Shinde@windriver.com"><Yash.Shinde@windriver.com></a></pre> \
<pre>+</pre> <pre>+---</pre>
<pre>+ bfd/ChangeLog \
| 12 +++++</pre> <pre>+ \
bfd/dwarf2.c \
| 86 ++++++++++++++++++++----------</pre> <pre>+ \
ld/ChangeLog \
| 5 ++</pre> <pre>+ ld/testsuite/ld-x86-64/pr27587.err \
| 2 +-</pre> <pre>+ 4 files changed, 76 insertions(+), 29 deletions(-)</pre>
<pre>+</pre>
<pre>+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c</pre>
<pre>+index 0ae50a37..b7839ad6 100644</pre>
<pre>+--- a/bfd/dwarf2.c</pre>
<pre>++++ b/bfd/dwarf2.c</pre>
<pre>+@@ -1571,6 +1571,7 @@ struct line_info_table</pre>
<pre>+ unsigned int num_files;</pre>
<pre>+ unsigned int num_dirs;</pre>
<pre>+ unsigned int num_sequences;</pre>
<pre>++ bool \
use_dir_and_file_0;</pre> <pre>+ char \
* comp_dir;</pre> \
<pre>+ char ** \
dirs;</pre> <pre>+ struct fileinfo* files;</pre>
<pre>+@@ -1791,16 +1792,30 @@ concat_filename (struct line_info_table *table, \
unsigned int file)</pre> <pre>+ {</pre>
<pre>+ char *filename;</pre>
<pre>+</pre>
<pre>+- if (table == NULL || file - 1 >= table->num_files)</pre>
<pre>++ /* Pre DWARF-5 entry 0 in the directory and filename tables was not \
used.</pre> <pre>++ So in order to save space in the tables \
used here the info for, eg</pre> <pre>++ directory 1 is \
stored in slot 0 of the directory table, directory 2</pre> \
<pre>++ in slot 1 and so on.</pre> <pre>++</pre>
<pre>++ Starting with DWARF-5 the 0'th entry is used so there \
is a one to one</pre> <pre>++ mapping between DWARF slots and \
internal table entries. */</pre> <pre>++ if (! \
table->use_dir_and_file_0)</pre> <pre>+ {</pre>
<pre>+- /* FILE == 0 means unknown. */</pre>
<pre>+- if (file)</pre>
<pre>+- _bfd_error_handler</pre>
<pre>+- (_("DWARF error: mangled line \
number section (bad file number)"));</pre> <pre>++ \
/* Pre DWARF-5, FILE == 0 means unknown. */</pre> \
<pre>++ if (file == 0)</pre> \
<pre>++ return strdup \
("<unknown>");</pre> <pre>++ -- \
file;</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>++ if (table == NULL || file >= table->num_files)</pre>
<pre>++ {</pre>
<pre>++ _bfd_error_handler</pre>
<pre>++ (_("DWARF error: mangled line number \
section (bad file number)"));</pre> <pre>+ \
return strdup ("<unknown>");</pre> <pre>+ \
}</pre> <pre>+</pre>
<pre>+- filename = table->files[file - 1].name;</pre>
<pre>++ filename = table->files[file].name;</pre>
<pre>++</pre>
<pre>+ if (filename == NULL)</pre>
<pre>+ return strdup ("<unknown>");</pre>
<pre>+</pre>
<pre>+@@ -1811,12 +1826,17 @@ concat_filename (struct line_info_table *table, \
unsigned int file)</pre> <pre>+ char *name;</pre>
<pre>+ size_t len;</pre>
<pre>+</pre>
<pre>+- if (table->files[file - 1].dir</pre>
<pre>++ if (table->files[file].dir</pre>
<pre>+ /* PR 17512: file: 0317e960. */</pre>
<pre>+- && table->files[file - \
1].dir <= table->num_dirs</pre> <pre>++ \
&& table->files[file].dir <= table->num_dirs</pre> <pre>+ \
/* PR 17512: file: 7f3d2e4b. */</pre> <pre>+ && \
table->dirs != NULL)</pre> <pre>+- subdir_name \
= table->dirs[table->files[file - 1].dir - 1];</pre> \
<pre>++ {</pre> \
<pre>++ if \
(table->use_dir_and_file_0)</pre> <pre>++ \
subdir_name = table->dirs[table->files[file].dir];</pre> \
<pre>++ else</pre> \
<pre>++ subdir_name = \
table->dirs[table->files[file].dir - 1];</pre> \
<pre>++ }</pre> <pre>+</pre>
<pre>+ if (!subdir_name || !IS_ABSOLUTE_PATH \
(subdir_name))</pre> <pre>+ dir_name = table->comp_dir;</pre>
<pre>+@@ -1857,10 +1877,12 @@ concat_filename (struct line_info_table *table, \
unsigned int file)</pre> <pre>+</pre>
<pre>+ /* Check whether [low1, high1) can be combined with [low2, high2),</pre>
<pre>+ i.e., they touch or overlap. */</pre>
<pre>+-static bool ranges_overlap (bfd_vma low1,</pre>
<pre>+- \
bfd_vma high1,</pre> \
<pre>+- \
bfd_vma low2,</pre> \
<pre>+- \
bfd_vma high2)</pre> <pre>++</pre>
<pre>++static bool</pre>
<pre>++ranges_overlap (bfd_vma low1,</pre>
<pre>++ \
bfd_vma high1,</pre> \
<pre>++ \
bfd_vma low2,</pre> <pre>++ \
bfd_vma high2)</pre> <pre>+ {</pre>
<pre>+ if (low1 == low2 || high1 == high2)</pre>
<pre>+ return true;</pre>
<pre>+@@ -1887,15 +1909,16 @@ static bool ranges_overlap (bfd_vma low1,</pre>
<pre>+ /* Insert an address range in the trie mapping addresses to compilation \
units.</pre> <pre>+ Will return the new trie node (usually the same \
as is being sent in, but</pre> <pre>+ in case of a leaf-to-interior \
conversion, or expansion of a leaf, it may be</pre> <pre>+- different), \
or NULL on failure.</pre> <pre>+- */</pre>
<pre>+-static struct trie_node *insert_arange_in_trie(bfd *abfd,</pre>
<pre>+- \
struct trie_node *trie,</pre> \
<pre>+- \
\
bfd_vma trie_pc,</pre> \
<pre>+- \
unsigned int trie_pc_bits,</pre> \
<pre>+- \
struct comp_unit *unit,</pre> \
<pre>+- \
bfd_vma low_pc,</pre> \
<pre>+- \
bfd_vma high_pc)</pre> <pre>++ \
different), or NULL on failure. */</pre> <pre>++</pre>
<pre>++static struct trie_node *</pre>
<pre>++insert_arange_in_trie (bfd *abfd,</pre>
<pre>++ \
struct trie_node *trie,</pre> \
<pre>++ \
bfd_vma trie_pc,</pre> \
<pre>++ \
unsigned int trie_pc_bits,</pre> \
<pre>++ \
struct comp_unit *unit,</pre> \
<pre>++ \
bfd_vma low_pc,</pre> \
<pre>++ \
bfd_vma high_pc)</pre> <pre>+ {</pre>
<pre>+ bfd_vma clamped_low_pc, clamped_high_pc;</pre>
<pre>+ int ch, from_ch, to_ch;</pre>
<pre>+@@ -2031,7 +2054,6 @@ static struct trie_node *insert_arange_in_trie(bfd \
*abfd,</pre> <pre>+ return trie;</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>+-</pre>
<pre>+ static bool</pre>
<pre>+ arange_add (struct comp_unit *unit, struct arange *first_arange,</pre>
<pre>+ struct trie_node **trie_root, bfd_vma low_pc, bfd_vma \
high_pc)</pre> <pre>+@@ -2412,10 +2434,8 @@ read_formatted_entries (struct comp_unit \
*unit, bfd_byte **bufp,</pre> <pre>+ }</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>+- /* Skip the first "zero entry", which \
is the compilation dir/file. */</pre> <pre>+- if \
(datai != 0)</pre> <pre>+- if (!callback (table, \
fe.name, fe.dir, fe.time, fe.size))</pre> <pre>+- \
return false;</pre> <pre>++ if (!callback \
(table, fe.name, fe.dir, fe.time, fe.size))</pre> \
<pre>++ return false;</pre> \
<pre>+ }</pre> <pre>+</pre>
<pre>+ *bufp = buf;</pre>
<pre>+@@ -2592,6 +2612,7 @@ decode_line_info (struct comp_unit *unit)</pre>
<pre>+ if (!read_formatted_entries (unit, \
&line_ptr, line_end, table,</pre> \
<pre>+ \
line_info_add_file_name))</pre> <pre>+ goto fail;</pre>
<pre>++ table->use_dir_and_file_0 = true;</pre>
<pre>+ }</pre>
<pre>+ else</pre>
<pre>+ {</pre>
<pre>+@@ -2614,6 +2635,7 @@ decode_line_info (struct comp_unit *unit)</pre>
<pre>+ if (!line_info_add_file_name (table, cur_file, dir, xtime, size))</pre>
<pre>+ goto fail;</pre>
<pre>+ }</pre>
<pre>++ table->use_dir_and_file_0 = false;</pre>
<pre>+ }</pre>
<pre>+</pre>
<pre>+ /* Read the statement sequences until there's nothing left. \
*/</pre> <pre>+@@ -2622,7 +2644,7 @@ decode_line_info (struct comp_unit *unit)</pre>
<pre>+ /* State machine registers. */</pre>
<pre>+ bfd_vma address = 0;</pre>
<pre>+ unsigned char op_index = 0;</pre>
<pre>+- char * filename = table->num_files ? \
concat_filename (table, 1) : NULL;</pre> <pre>++ char * \
filename = NULL;</pre> <pre>+ unsigned int line = \
1;</pre> <pre>+ unsigned int column = 0;</pre>
<pre>+ unsigned int discriminator = 0;</pre>
<pre>+@@ -2637,6 +2659,14 @@ decode_line_info (struct comp_unit *unit)</pre>
<pre>+ bfd_vma low_pc = (bfd_vma) -1;</pre>
<pre>+ bfd_vma high_pc = 0;</pre>
<pre>+</pre>
<pre>++ if (table->num_files)</pre>
<pre>++ {</pre>
<pre>++ if \
(table->use_dir_and_file_0)</pre> <pre>++ \
filename = concat_filename (table, 0);</pre> \
<pre>++ else</pre> \
<pre>++ filename = \
concat_filename (table, 1);</pre> <pre>++ }</pre>
<pre>++</pre>
<pre>+ /* Decode the table. */</pre>
<pre>+ while (!end_sequence && line_ptr \
< line_end)</pre> <pre>+ {</pre>
<pre>+diff --git a/ld/testsuite/ld-x86-64/pr27587.err \
b/ld/testsuite/ld-x86-64/pr27587.err</pre> <pre>+index fa870790..807750ca \
100644</pre> <pre>+--- a/ld/testsuite/ld-x86-64/pr27587.err</pre>
<pre>++++ b/ld/testsuite/ld-x86-64/pr27587.err</pre>
<pre>+@@ -1,3 +1,3 @@</pre>
<pre>+ #...</pre>
<pre>+-.*pr27587.i:4: undefined reference to `stack_size'</pre>
<pre>++.*pr27587/<artificial>:4: undefined reference to `stack_size'</pre>
<pre>+ #...</pre>
<pre>diff --git a/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch \
b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch</pre> <pre>new \
file mode 100644</pre> <pre>index 0000000000..603824155b</pre>
<pre>--- /dev/null</pre>
<pre>+++ b/meta/recipes-devtools/binutils/binutils/0020-CVE-2023-22608-3.patch</pre>
<pre>@@ -0,0 +1,33 @@</pre>
<pre>+From 20c75f063a999f9e849a77613a82b15de78ea45f Mon Sep 17 00:00:00 2001</pre>
<pre>+From: Nick Clifton <a \
href="mailto:nickc@redhat.com"><nickc@redhat.com></a></pre> <pre>+Date: Fri, 23 \
Dec 2022 13:02:04 +0000</pre> <pre>+Subject: [PATCH] Fix illegal memory access \
parsing corrupt DWARF information.</pre> <pre>+</pre>
<pre>+ PR 29936</pre>
<pre>+ * dwarf2.c (concat_filename): Fix check for a directory index off</pre>
<pre>+ the end of the directory table.</pre>
<pre>+</pre>
<pre>+Upstream-Status: Backport [<a \
href="https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009 \
bc9b243cd4dfa10ae1ac09">https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=8af23b30edbaedf009bc9b243cd4dfa10ae1ac09</a>]</pre>
<pre>+CVE: CVE-2023-22608</pre>
<pre>+</pre>
<pre>+Signed-off-by: Yash Shinde <a \
href="mailto:Yash.Shinde@windriver.com"><Yash.Shinde@windriver.com></a></pre> \
<pre>+</pre> <pre>+---</pre>
<pre>+ bfd/ChangeLog | 6 ++++++</pre>
<pre>+ bfd/dwarf2.c | 3 ++-</pre>
<pre>+ 2 files changed, 8 insertions(+), 1 deletion(-)</pre>
<pre>+</pre>
<pre>+diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c</pre>
<pre>+index b7839ad6..8b07a24c 100644</pre>
<pre>+--- a/bfd/dwarf2.c</pre>
<pre>++++ b/bfd/dwarf2.c</pre>
<pre>+@@ -1828,7 +1828,8 @@ concat_filename (struct line_info_table *table, unsigned \
int file)</pre> <pre>+</pre>
<pre>+ if (table->files[file].dir</pre>
<pre>+ /* PR 17512: file: 0317e960. */</pre>
<pre>+- && \
table->files[file].dir <= table->num_dirs</pre> \
<pre>++ && \
table->files[file].dir</pre> <pre>++ \
<= (table->use_dir_and_file_0 ? table->num_dirs - 1 : \
table->num_dirs)</pre> <pre>+ /* PR 17512: file: 7f3d2e4b. */</pre>
<pre>+ && table->dirs != NULL)</pre>
<pre>+ {</pre>
</blockquote>
<p><o:p> </o:p></p>
<pre>-- </pre>
<pre># Randy MacLeod</pre>
<pre># Wind River Linux</pre>
<p class="MsoNormal"><span style="font-size:10.0pt;font-family:"Courier \
New""><o:p> </o:p></span></p> </div>
</body>
</html>
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#177818): https://lists.openembedded.org/g/openembedded-core/message/177818
Mute This Topic: https://lists.openembedded.org/mt/97242671/4454766
Group Owner: openembedded-core+owner@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [openembedded-core@marc.info]
-=-=-=-=-=-=-=-=-=-=-=-
--VZ2G4nVkF2cFL13gc4uI--
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic