diff mbox series

[3/9,libbacktrace] Handle alt FORMS without .gnu_debugaltlink

Message ID 20181211101411.7067-4-tdevries@suse.de
State New
Headers show
Series Handle .gnu_debugaltlink | expand

Commit Message

Tom de Vries Dec. 11, 2018, 10:14 a.m. UTC
Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
presence of missing .gnu_debugaltlink file.

2018-11-11  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
	(read_attribute): Add altlink parameter.  Handle missing altlink for
	DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
	(find_address_ranges, build_address_map, build_dwarf_data): Add and
	handle altlink parameter.
	(read_referenced_name, read_function_entry): Add argument to
	read_attribute call.
---
 libbacktrace/dwarf.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

Comments

Ian Lance Taylor Jan. 16, 2019, 1:06 a.m. UTC | #1
On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>
> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
> presence of missing .gnu_debugaltlink file.
>
> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>
>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
>         (read_attribute): Add altlink parameter.  Handle missing altlink for
>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
>         (find_address_ranges, build_address_map, build_dwarf_data): Add and
>         handle altlink parameter.
>         (read_referenced_name, read_function_entry): Add argument to
>         read_attribute call.



>  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
>                 int is_dwarf64, int version, int addrsize,
>                 const unsigned char *dwarf_str, size_t dwarf_str_size,
> -               struct attr_val *val)
> +               struct attr_val *val, struct dwarf_data *altlink)
>  {

altlink is not a result parameter, so it should be before val.


> @@ -1277,7 +1289,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
>                      size_t dwarf_ranges_size,
>                      int is_bigendian, backtrace_error_callback error_callback,
>                      void *data, struct unit *u,
> -                    struct unit_addrs_vector *addrs)
> +                    struct unit_addrs_vector *addrs,
> +                    struct dwarf_data *altlink)

Same.  altlink should be before the error_callback parameter.


> @@ -1431,7 +1444,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>                    const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
>                    const unsigned char *dwarf_str, size_t dwarf_str_size,
>                    int is_bigendian, backtrace_error_callback error_callback,
> -                  void *data, struct unit_addrs_vector *addrs)
> +                  void *data, struct unit_addrs_vector *addrs,
> +                  struct dwarf_data *altlink)

Same.

Ian
Tom de Vries Jan. 16, 2019, 4:35 p.m. UTC | #2
On 16-01-19 02:06, Ian Lance Taylor wrote:
> On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
>>
>> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
>> presence of missing .gnu_debugaltlink file.
>>
>> 2018-11-11  Tom de Vries  <tdevries@suse.de>
>>
>>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
>>         (read_attribute): Add altlink parameter.  Handle missing altlink for
>>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
>>         (find_address_ranges, build_address_map, build_dwarf_data): Add and
>>         handle altlink parameter.
>>         (read_referenced_name, read_function_entry): Add argument to
>>         read_attribute call.
> 
> 
> 
>>  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
>>                 int is_dwarf64, int version, int addrsize,
>>                 const unsigned char *dwarf_str, size_t dwarf_str_size,
>> -               struct attr_val *val)
>> +               struct attr_val *val, struct dwarf_data *altlink)
>>  {
> 
> altlink is not a result parameter, so it should be before val.
> 
> 

Done.

>> @@ -1277,7 +1289,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
>>                      size_t dwarf_ranges_size,
>>                      int is_bigendian, backtrace_error_callback error_callback,
>>                      void *data, struct unit *u,
>> -                    struct unit_addrs_vector *addrs)
>> +                    struct unit_addrs_vector *addrs,
>> +                    struct dwarf_data *altlink)
> 
> Same.  altlink should be before the error_callback parameter.
> 
> 

Done.

>> @@ -1431,7 +1444,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
>>                    const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
>>                    const unsigned char *dwarf_str, size_t dwarf_str_size,
>>                    int is_bigendian, backtrace_error_callback error_callback,
>> -                  void *data, struct unit_addrs_vector *addrs)
>> +                  void *data, struct unit_addrs_vector *addrs,
>> +                  struct dwarf_data *altlink)
> 
> Same.
> 

Done.

Thanks,
- Tom
[libbacktrace] Handle alt FORMS without .gnu_debugaltlink

Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
presence of missing .gnu_debugaltlink file.

2018-11-11  Tom de Vries  <tdevries@suse.de>

	* dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
	(read_attribute): Add altlink parameter.  Handle missing altlink for
	DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
	(find_address_ranges, build_address_map, build_dwarf_data): Add and
	handle altlink parameter.
	(read_referenced_name, read_function_entry): Add argument to
	read_attribute call.

---
 libbacktrace/dwarf.c | 44 +++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 5469f968468..0e2d57122a2 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -129,6 +129,8 @@ struct abbrevs
 
 enum attr_val_encoding
 {
+  /* No attribute value.  */
+  ATTR_VAL_NONE,
   /* An address.  */
   ATTR_VAL_ADDRESS,
   /* A unsigned integer.  */
@@ -700,7 +702,7 @@ static int
 read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 		int is_dwarf64, int version, int addrsize,
 		const unsigned char *dwarf_str, size_t dwarf_str_size,
-		struct attr_val *val)
+		struct dwarf_data *altlink, struct attr_val *val)
 {
   /* Avoid warnings about val.u.FIELD may be used uninitialized if
      this function is inlined.  The warnings aren't valid but can
@@ -806,7 +808,7 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	form = read_uleb128 (buf);
 	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
 			       version, addrsize, dwarf_str, dwarf_str_size,
-			       val);
+			       altlink, val);
       }
     case DW_FORM_sec_offset:
       val->encoding = ATTR_VAL_REF_SECTION;
@@ -832,12 +834,22 @@ read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->u.uint = read_uleb128 (buf);
       return 1;
     case DW_FORM_GNU_ref_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
@@ -1275,9 +1287,9 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     const unsigned char *dwarf_str, size_t dwarf_str_size,
 		     const unsigned char *dwarf_ranges,
 		     size_t dwarf_ranges_size,
-		     int is_bigendian, backtrace_error_callback error_callback,
-		     void *data, struct unit *u,
-		     struct unit_addrs_vector *addrs)
+		     int is_bigendian, struct dwarf_data *altlink,
+		     backtrace_error_callback error_callback, void *data,
+		     struct unit *u, struct unit_addrs_vector *addrs)
 {
   while (unit_buf->left > 0)
     {
@@ -1313,7 +1325,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
-			       dwarf_str, dwarf_str_size, &val))
+			       dwarf_str, dwarf_str_size, altlink, &val))
 	    return 0;
 
 	  switch (abbrev->attrs[i].name)
@@ -1411,7 +1423,7 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 	  if (!find_address_ranges (state, base_address, unit_buf,
 				    dwarf_str, dwarf_str_size,
 				    dwarf_ranges, dwarf_ranges_size,
-				    is_bigendian, error_callback, data,
+				    is_bigendian, altlink, error_callback, data,
 				    u, addrs))
 	    return 0;
 	}
@@ -1430,8 +1442,9 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
 		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
 		   const unsigned char *dwarf_str, size_t dwarf_str_size,
-		   int is_bigendian, backtrace_error_callback error_callback,
-		   void *data, struct unit_addrs_vector *addrs)
+		   int is_bigendian, struct dwarf_data *altlink,
+		   backtrace_error_callback error_callback, void *data,
+		   struct unit_addrs_vector *addrs)
 {
   struct dwarf_buf info;
   struct backtrace_vector units;
@@ -1532,7 +1545,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
       if (!find_address_ranges (state, base_address, &unit_buf,
 				dwarf_str, dwarf_str_size,
 				dwarf_ranges, dwarf_ranges_size,
-				is_bigendian, error_callback, data,
+				is_bigendian, altlink, error_callback, data,
 				u, addrs))
 	goto fail;
 
@@ -2147,7 +2160,7 @@ read_referenced_name (struct dwarf_data *ddata, struct unit *u,
       if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
 			   u->is_dwarf64, u->version, u->addrsize,
 			   ddata->dwarf_str, ddata->dwarf_str_size,
-			   &val))
+			   ddata->altlink, &val))
 	return NULL;
 
       switch (abbrev->attrs[i].name)
@@ -2369,7 +2382,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
 			       ddata->dwarf_str, ddata->dwarf_str_size,
-			       &val))
+			       ddata->altlink, &val))
 	    return 0;
 
 	  /* The compile unit sets the base address for any address
@@ -2995,7 +3008,8 @@ build_dwarf_data (struct backtrace_state *state,
   if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
 			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
 			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
-			  is_bigendian, error_callback, data, &addrs_vec))
+			  is_bigendian, altlink, error_callback, data,
+			  &addrs_vec))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))
Ian Lance Taylor Jan. 16, 2019, 6:24 p.m. UTC | #3
On Wed, Jan 16, 2019 at 8:35 AM Tom de Vries <tdevries@suse.de> wrote:
>
> On 16-01-19 02:06, Ian Lance Taylor wrote:
> > On Tue, Dec 11, 2018 at 2:14 AM Tom de Vries <tdevries@suse.de> wrote:
> >>
> >> Handle DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt references robustly in
> >> presence of missing .gnu_debugaltlink file.
> >>
> >> 2018-11-11  Tom de Vries  <tdevries@suse.de>
> >>
> >>         * dwarf.c (enum attr_val_encoding): Add ATTR_VAL_NONE.
> >>         (read_attribute): Add altlink parameter.  Handle missing altlink for
> >>         DW_FORM_GNU_strp_alt and DW_FORM_GNU_ref_alt.
> >>         (find_address_ranges, build_address_map, build_dwarf_data): Add and
> >>         handle altlink parameter.
> >>         (read_referenced_name, read_function_entry): Add argument to
> >>         read_attribute call.
> >
> >
> >
> >>  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
> >>                 int is_dwarf64, int version, int addrsize,
> >>                 const unsigned char *dwarf_str, size_t dwarf_str_size,
> >> -               struct attr_val *val)
> >> +               struct attr_val *val, struct dwarf_data *altlink)
> >>  {
> >
> > altlink is not a result parameter, so it should be before val.
> >
> >
>
> Done.
>
> >> @@ -1277,7 +1289,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
> >>                      size_t dwarf_ranges_size,
> >>                      int is_bigendian, backtrace_error_callback error_callback,
> >>                      void *data, struct unit *u,
> >> -                    struct unit_addrs_vector *addrs)
> >> +                    struct unit_addrs_vector *addrs,
> >> +                    struct dwarf_data *altlink)
> >
> > Same.  altlink should be before the error_callback parameter.
> >
> >
>
> Done.
>
> >> @@ -1431,7 +1444,8 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
> >>                    const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
> >>                    const unsigned char *dwarf_str, size_t dwarf_str_size,
> >>                    int is_bigendian, backtrace_error_callback error_callback,
> >> -                  void *data, struct unit_addrs_vector *addrs)
> >> +                  void *data, struct unit_addrs_vector *addrs,
> >> +                  struct dwarf_data *altlink)
> >
> > Same.
> >
>
> Done.

This patch is OK.

Thanks.

Ian
diff mbox series

Patch

diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index b571c9fbb06..8b802a085ca 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -129,6 +129,8 @@  struct abbrevs
 
 enum attr_val_encoding
 {
+  /* No attribute value.  */
+  ATTR_VAL_NONE,
   /* An address.  */
   ATTR_VAL_ADDRESS,
   /* A unsigned integer.  */
@@ -700,7 +702,7 @@  static int
 read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 		int is_dwarf64, int version, int addrsize,
 		const unsigned char *dwarf_str, size_t dwarf_str_size,
-		struct attr_val *val)
+		struct attr_val *val, struct dwarf_data *altlink)
 {
   /* Avoid warnings about val.u.FIELD may be used uninitialized if
      this function is inlined.  The warnings aren't valid but can
@@ -806,7 +808,7 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	form = read_uleb128 (buf);
 	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
 			       version, addrsize, dwarf_str, dwarf_str_size,
-			       val);
+			       val, altlink);
       }
     case DW_FORM_sec_offset:
       val->encoding = ATTR_VAL_REF_SECTION;
@@ -832,12 +834,22 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->u.uint = read_uleb128 (buf);
       return 1;
     case DW_FORM_GNU_ref_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     case DW_FORM_GNU_strp_alt:
-      val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
+      if (altlink == NULL)
+	{
+	  val->encoding = ATTR_VAL_NONE;
+	  return 1;
+	}
+      val->encoding = ATTR_VAL_REF_SECTION;
       return 1;
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
@@ -1277,7 +1289,8 @@  find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 		     size_t dwarf_ranges_size,
 		     int is_bigendian, backtrace_error_callback error_callback,
 		     void *data, struct unit *u,
-		     struct unit_addrs_vector *addrs)
+		     struct unit_addrs_vector *addrs,
+		     struct dwarf_data *altlink)
 {
   while (unit_buf->left > 0)
     {
@@ -1313,7 +1326,7 @@  find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
-			       dwarf_str, dwarf_str_size, &val))
+			       dwarf_str, dwarf_str_size, &val, altlink))
 	    return 0;
 
 	  switch (abbrev->attrs[i].name)
@@ -1412,7 +1425,7 @@  find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
 				    dwarf_str, dwarf_str_size,
 				    dwarf_ranges, dwarf_ranges_size,
 				    is_bigendian, error_callback, data,
-				    u, addrs))
+				    u, addrs, altlink))
 	    return 0;
 	}
     }
@@ -1431,7 +1444,8 @@  build_address_map (struct backtrace_state *state, uintptr_t base_address,
 		   const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
 		   const unsigned char *dwarf_str, size_t dwarf_str_size,
 		   int is_bigendian, backtrace_error_callback error_callback,
-		   void *data, struct unit_addrs_vector *addrs)
+		   void *data, struct unit_addrs_vector *addrs,
+		   struct dwarf_data *altlink)
 {
   struct dwarf_buf info;
   struct backtrace_vector units;
@@ -1533,7 +1547,7 @@  build_address_map (struct backtrace_state *state, uintptr_t base_address,
 				dwarf_str, dwarf_str_size,
 				dwarf_ranges, dwarf_ranges_size,
 				is_bigendian, error_callback, data,
-				u, addrs))
+				u, addrs, altlink))
 	goto fail;
 
       if (unit_buf.reported_underflow)
@@ -2146,7 +2160,7 @@  read_referenced_name (struct dwarf_data *ddata, struct unit *u,
       if (!read_attribute (abbrev->attrs[i].form, &unit_buf,
 			   u->is_dwarf64, u->version, u->addrsize,
 			   ddata->dwarf_str, ddata->dwarf_str_size,
-			   &val))
+			   &val, ddata->altlink))
 	return NULL;
 
       switch (abbrev->attrs[i].name)
@@ -2359,7 +2373,7 @@  read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
 	  if (!read_attribute (abbrev->attrs[i].form, unit_buf,
 			       u->is_dwarf64, u->version, u->addrsize,
 			       ddata->dwarf_str, ddata->dwarf_str_size,
-			       &val))
+			       &val, ddata->altlink))
 	    return 0;
 
 	  /* The compile unit sets the base address for any address
@@ -2980,7 +2994,8 @@  build_dwarf_data (struct backtrace_state *state,
   if (!build_address_map (state, base_address, dwarf_info, dwarf_info_size,
 			  dwarf_abbrev, dwarf_abbrev_size, dwarf_ranges,
 			  dwarf_ranges_size, dwarf_str, dwarf_str_size,
-			  is_bigendian, error_callback, data, &addrs_vec))
+			  is_bigendian, error_callback, data, &addrs_vec,
+			  altlink))
     return NULL;
 
   if (!backtrace_vector_release (state, &addrs_vec.vec, error_callback, data))