#include "auxv.h"
#include "gdb_bfd.h"
#include "probe.h"
+#include "rsp-low.h"
+
+#define NOTE_GNU_BUILD_ID_NAME ".note.gnu.build-id"
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
CORE_ADDR addr = 0;
- volatile struct gdb_exception ex;
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
ptr_type);
}
- exception_print (gdb_stderr, ex);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
+
return addr;
}
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- ULONGEST version;
+ ULONGEST version = 0;
+
+ TRY
+ {
+ /* Check version, and return zero if `struct r_debug' doesn't have
+ the r_ldsomap member. */
+ version
+ = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
+ lmo->r_version_size, byte_order);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
- /* Check version, and return zero if `struct r_debug' doesn't have
- the r_ldsomap member. */
- version
- = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
- lmo->r_version_size, byte_order);
if (version < 2 || lmo->r_ldsomap_offset == -1)
return 0;
return (name_lm >= vaddr && name_lm < vaddr + size);
}
+/* Validate SO by comparing build-id from the associated bfd and
+ corresponding build-id from target memory. Return NULL for success
+ or a string for error. Caller must call xfree for the error string. */
+
+static char *
+svr4_validate (const struct so_list *const so)
+{
+ const bfd_byte *local_id;
+ size_t local_idsz;
+
+ gdb_assert (so != NULL);
+
+ /* Target doesn't support reporting the build ID or the remote shared library
+ does not have build ID. */
+ if (so->build_id == NULL)
+ return NULL;
+
+ /* Build ID may be present in the local file, just GDB is unable to retrieve
+ it. As it has been reported by gdbserver it is not FSF gdbserver. */
+ if (so->abfd == NULL
+ || !bfd_check_format (so->abfd, bfd_object))
+ return NULL;
+
+ /* GDB has verified the local file really does not contain the build ID. */
+ if (so->abfd->build_id == NULL)
+ {
+ char *remote_hex;
+
+ remote_hex = alloca (so->build_idsz * 2 + 1);
+ bin2hex (so->build_id, remote_hex, so->build_idsz);
+
+ return xstrprintf (_("remote build ID is %s "
+ "but local file does not have build ID"),
+ remote_hex);
+ }
+
+ local_id = so->abfd->build_id->data;
+ local_idsz = so->abfd->build_id->size;
+
+ if (so->build_idsz != local_idsz
+ || memcmp (so->build_id, local_id, so->build_idsz) != 0)
+ {
+ char *remote_hex, *local_hex;
+
+ remote_hex = alloca (so->build_idsz * 2 + 1);
+ bin2hex (so->build_id, remote_hex, so->build_idsz);
+ local_hex = alloca (local_idsz * 2 + 1);
+ bin2hex (local_id, local_hex, local_idsz);
+
+ return xstrprintf (_("remote build ID %s "
+ "does not match local build ID %s"),
+ remote_hex, local_hex);
+ }
+
+ /* Both build IDs are present and they match. */
+ return NULL;
+}
+
/* Implement the "open_symbol_file_object" target_so_ops method.
If no open symbol file, attempt to locate and open the main symbol
newobj->lm_info = xmalloc (sizeof (struct lm_info));
memcpy (newobj->lm_info, src->lm_info, sizeof (struct lm_info));
+ if (newobj->build_id != NULL)
+ {
+ newobj->build_id = xmalloc (src->build_idsz);
+ memcpy (newobj->build_id, src->build_id, src->build_idsz);
+ }
+
newobj->next = NULL;
*link = newobj;
link = &newobj->next;
ULONGEST *lmp = xml_find_attribute (attributes, "lm")->value;
ULONGEST *l_addrp = xml_find_attribute (attributes, "l_addr")->value;
ULONGEST *l_ldp = xml_find_attribute (attributes, "l_ld")->value;
+ const struct gdb_xml_value *const att_build_id
+ = xml_find_attribute (attributes, "build-id");
+ const char *const hex_build_id = att_build_id ? att_build_id->value : NULL;
struct so_list *new_elem;
new_elem = XCNEW (struct so_list);
strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1);
new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
strcpy (new_elem->so_original_name, new_elem->so_name);
+ if (hex_build_id != NULL)
+ {
+ const size_t hex_build_id_len = strlen (hex_build_id);
+
+ if (hex_build_id_len == 0)
+ warning (_("Shared library \"%s\" received empty build-id "
+ "from gdbserver"), new_elem->so_original_name);
+ else if ((hex_build_id_len & 1U) != 0)
+ warning (_("Shared library \"%s\" received odd number "
+ "of build-id \"%s\" hex characters from gdbserver"),
+ new_elem->so_original_name, hex_build_id);
+ else
+ {
+ const size_t build_idsz = hex_build_id_len / 2;
+
+ new_elem->build_id = xmalloc (build_idsz);
+ new_elem->build_idsz = hex2bin (hex_build_id, new_elem->build_id,
+ build_idsz);
+ if (new_elem->build_idsz != build_idsz)
+ {
+ warning (_("Shared library \"%s\" received invalid "
+ "build-id \"%s\" hex character at encoded byte "
+ "position %s (first as 0) from gdbserver"),
+ new_elem->so_original_name, hex_build_id,
+ pulongest (new_elem->build_idsz));
+ xfree (new_elem->build_id);
+ new_elem->build_id = NULL;
+ new_elem->build_idsz = 0;
+ }
+ }
+ }
*list->tailp = new_elem;
list->tailp = &new_elem->next;
{ "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "build-id", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
struct so_list *so;
bfd *tmp_bfd = NULL;
struct target_ops *tmp_bfd_target;
- volatile struct gdb_exception ex;
sym_addr = 0;
be trivial on GNU/Linux). Therefore, we have to try an alternate
mechanism to find the dynamic linker's base address. */
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
tmp_bfd = solib_bfd_open (interp_name);
}
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ }
+ END_CATCH
+
if (tmp_bfd == NULL)
goto bkpt_at_symbol;
{
/* ENTRY_POINT is a possible function descriptor - before
a call to gdbarch_convert_from_func_ptr_addr. */
- CORE_ADDR entry_point, displacement;
+ CORE_ADDR entry_point, exec_displacement;
if (exec_bfd == NULL)
return 0;
if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) <= 0)
return 0;
- displacement = entry_point - bfd_get_start_address (exec_bfd);
+ exec_displacement = entry_point - bfd_get_start_address (exec_bfd);
- /* Verify the DISPLACEMENT candidate complies with the required page
+ /* Verify the EXEC_DISPLACEMENT candidate complies with the required page
alignment. It is cheaper than the program headers comparison below. */
if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
p_offset % p_align == p_vaddr % p_align
Kernel is free to load the executable with lower alignment. */
- if ((displacement & (elf->minpagesize - 1)) != 0)
+ if ((exec_displacement & (elf->minpagesize - 1)) != 0)
return 0;
}
printf_unfiltered (_("Using PIE (Position Independent Executable) "
"displacement %s for \"%s\".\n"),
- paddress (target_gdbarch (), displacement),
+ paddress (target_gdbarch (), exec_displacement),
bfd_get_filename (exec_bfd));
}
- *displacementp = displacement;
+ *displacementp = exec_displacement;
return 1;
}
svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
svr4_so_ops.handle_event = svr4_handle_solib_event;
+ svr4_so_ops.validate = svr4_validate;
}