View | Details | Raw Unified | Return to bug 20876 | Differences between
and this patch

Collapse All | Expand All

(-)a/bfd/bfd-in2.h (+2 lines)
Lines 1121-1126 struct bfd_section *bfd_create_gnu_debuglink_section Link Here
1121
bfd_boolean bfd_fill_in_gnu_debuglink_section
1121
bfd_boolean bfd_fill_in_gnu_debuglink_section
1122
   (bfd *abfd, struct bfd_section *sect, const char *filename);
1122
   (bfd *abfd, struct bfd_section *sect, const char *filename);
1123
1123
1124
char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
1125
1124
/* Extracted from libbfd.c.  */
1126
/* Extracted from libbfd.c.  */
1125
1127
1126
/* Byte swapping macros for user section data.  */
1128
/* Byte swapping macros for user section data.  */
(-)a/bfd/dwarf2.c (-1 / +5 lines)
Lines 3921-3927 _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd, Link Here
3921
  msec = find_debug_info (debug_bfd, debug_sections, NULL);
3921
  msec = find_debug_info (debug_bfd, debug_sections, NULL);
3922
  if (msec == NULL && abfd == debug_bfd)
3922
  if (msec == NULL && abfd == debug_bfd)
3923
    {
3923
    {
3924
      char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
3924
      char * debug_filename;
3925
3926
      debug_filename = bfd_follow_build_id_debuglink (abfd, DEBUGDIR);
3927
      if (debug_filename == NULL)
3928
	debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR);
3925
3929
3926
      if (debug_filename == NULL)
3930
      if (debug_filename == NULL)
3927
	/* No dwarf2 info, and no gnu_debuglink to follow.
3931
	/* No dwarf2 info, and no gnu_debuglink to follow.
(-)a/bfd/opncls.c (-33 / +209 lines)
Lines 25-30 Link Here
25
#include "objalloc.h"
25
#include "objalloc.h"
26
#include "libbfd.h"
26
#include "libbfd.h"
27
#include "libiberty.h"
27
#include "libiberty.h"
28
#include "elf-bfd.h"
28
29
29
#ifndef S_IXUSR
30
#ifndef S_IXUSR
30
#define S_IXUSR 0100	/* Execute by owner.  */
31
#define S_IXUSR 0100	/* Execute by owner.  */
Lines 1336-1352 INTERNAL_FUNCTION Link Here
1336
	find_separate_debug_file
1337
	find_separate_debug_file
1337
1338
1338
SYNOPSIS
1339
SYNOPSIS
1339
	char *find_separate_debug_file (bfd *abfd);
1340
	char *find_separate_debug_file
1341
	  (bfd *abfd, const char *dir, bfd_boolean include_dirs,
1342
	   get_func_type get, check_func_type check);
1340
1343
1341
DESCRIPTION
1344
DESCRIPTION
1342
	Searches @var{abfd} for a section called @var{section_name} which
1345
	Searches for a debug information file corresponding to @var{abfd}.
1343
	is expected to contain a reference to a file containing separate
1346
	The name of the separate debug info file is returned by the @var{get}
1344
	debugging information.  The function scans various locations in
1347
	function.  This function scans various fixed locations in the
1345
	the filesystem, including the file tree rooted at
1348
	filesystem, including the file tree rooted at @var{dir}.  If the
1346
	@var{debug_file_directory}, and returns the first matching
1349
	@var{include_dirs} parameter is true then the directory components of
1347
	filename that it finds.  If @var{check_crc} is TRUE then the
1350
	@var{abfd}'s filename will be included in the searched locations.
1348
	contents of the file must also match the CRC value contained in
1351
1349
	@var{section_name}.  Returns NULL if no valid file could be found.
1352
	Returns the filename of the first file to be found which receives a
1353
	TRUE result from the @var{check} function.  Returns NULL if no valid
1354
	file could be found.
1350
*/
1355
*/
1351
1356
1352
typedef char *      (* get_func_type) (bfd *, unsigned long *);
1357
typedef char *      (* get_func_type) (bfd *, unsigned long *);
Lines 1355-1360 typedef bfd_boolean (* check_func_type) (const char *, const unsigned long); Link Here
1355
static char *
1360
static char *
1356
find_separate_debug_file (bfd *           abfd,
1361
find_separate_debug_file (bfd *           abfd,
1357
			  const char *    debug_file_directory,
1362
			  const char *    debug_file_directory,
1363
			  bfd_boolean     include_dirs,
1358
			  get_func_type   get_func,
1364
			  get_func_type   get_func,
1359
			  check_func_type check_func)
1365
			  check_func_type check_func)
1360
{
1366
{
Lines 1389-1406 find_separate_debug_file (bfd * abfd, Link Here
1389
      return NULL;
1395
      return NULL;
1390
    }
1396
    }
1391
1397
1392
  for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--)
1398
  if (include_dirs)
1393
    if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1]))
1399
    {
1394
      break;
1400
      for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--)
1401
	if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1]))
1402
	  break;
1395
1403
1396
  dir = (char *) bfd_malloc (dirlen + 1);
1404
      dir = (char *) bfd_malloc (dirlen + 1);
1397
  if (dir == NULL)
1405
      if (dir == NULL)
1406
	{
1407
	  free (base);
1408
	  return NULL;
1409
	}
1410
      memcpy (dir, abfd->filename, dirlen);
1411
      dir[dirlen] = '\0';
1412
    }
1413
  else
1398
    {
1414
    {
1399
      free (base);
1415
      dir = (char *) bfd_malloc (1);
1400
      return NULL;
1416
      * dir = 0;
1417
      dirlen = 0;
1401
    }
1418
    }
1402
  memcpy (dir, abfd->filename, dirlen);
1403
  dir[dirlen] = '\0';
1404
1419
1405
  /* Compute the canonical name of the bfd object with all symbolic links
1420
  /* Compute the canonical name of the bfd object with all symbolic links
1406
     resolved, for use in the global debugfile directory.  */
1421
     resolved, for use in the global debugfile directory.  */
Lines 1410-1439 find_separate_debug_file (bfd * abfd, Link Here
1410
      break;
1425
      break;
1411
  canon_dir[canon_dirlen] = '\0';
1426
  canon_dir[canon_dirlen] = '\0';
1412
1427
1428
#ifndef EXTRA_DEBUG_ROOT1
1429
#define EXTRA_DEBUG_ROOT1 "/usr/lib/debug"
1430
#endif
1431
#ifndef EXTRA_DEBUG_ROOT2
1432
#define EXTRA_DEBUG_ROOT2 "/usr/lib/debug/usr"
1433
#endif  
1434
1413
  debugfile = (char *)
1435
  debugfile = (char *)
1414
      bfd_malloc (strlen (debug_file_directory) + 1
1436
      bfd_malloc (strlen (debug_file_directory) + 1
1415
                  + (canon_dirlen > dirlen ? canon_dirlen : dirlen)
1437
                  + (canon_dirlen > dirlen ? canon_dirlen : dirlen)
1416
                  + strlen (".debug/")
1438
                  + strlen (".debug/")
1439
#ifdef EXTRA_DEBUG_ROOT1
1440
		  + strlen (EXTRA_DEBUG_ROOT1)
1441
#endif
1442
#ifdef EXTRA_DEBUG_ROOT2
1443
		  + strlen (EXTRA_DEBUG_ROOT2)
1444
#endif
1417
                  + strlen (base)
1445
                  + strlen (base)
1418
                  + 1);
1446
                  + 1);
1419
  if (debugfile == NULL)
1447
  if (debugfile == NULL)
1420
    goto found; /* Actually this returns NULL.  */
1448
    goto found; /* Actually this returns NULL.  */
1421
1449
1422
  /* First try in the same directory as the original file:  */
1450
  /* First try in the same directory as the original file:  */
1423
  strcpy (debugfile, dir);
1451
  sprintf (debugfile, "%s%s", dir, base);
1424
  strcat (debugfile, base);
1425
1426
  if (check_func (debugfile, crc32))
1452
  if (check_func (debugfile, crc32))
1427
    goto found;
1453
    goto found;
1428
1454
1429
  /* Then try in a subdirectory called .debug.  */
1455
  /* Then try in a subdirectory called .debug.  */
1430
  strcpy (debugfile, dir);
1456
  sprintf (debugfile, "%s.debug/%s", dir, base);
1431
  strcat (debugfile, ".debug/");
1457
  if (check_func (debugfile, crc32))
1432
  strcat (debugfile, base);
1458
    goto found;
1433
1459
1460
#ifdef EXTRA_DEBUG_ROOT1
1461
  /* Try the first extra debug file root.  */
1462
  sprintf (debugfile, "%s%s%s", EXTRA_DEBUG_ROOT1, canon_dir, base);
1434
  if (check_func (debugfile, crc32))
1463
  if (check_func (debugfile, crc32))
1435
    goto found;
1464
    goto found;
1465
#endif
1436
1466
1467
#ifdef EXTRA_DEBUG_ROOT2
1468
  /* Try the second extra debug file root.  */
1469
  sprintf (debugfile, "%s%s%s", EXTRA_DEBUG_ROOT2, canon_dir, base);
1470
  if (check_func (debugfile, crc32))
1471
    goto found;
1472
#endif
1473
  
1437
  /* Then try in the global debugfile directory.  */
1474
  /* Then try in the global debugfile directory.  */
1438
  strcpy (debugfile, debug_file_directory);
1475
  strcpy (debugfile, debug_file_directory);
1439
  dirlen = strlen (debug_file_directory) - 1;
1476
  dirlen = strlen (debug_file_directory) - 1;
Lines 1475-1483 DESCRIPTION Link Here
1475
	locations, including the directory tree rooted at @var{dir}, and if
1512
	locations, including the directory tree rooted at @var{dir}, and if
1476
	found returns the full filename.
1513
	found returns the full filename.
1477
1514
1478
	If @var{dir} is NULL, it will search a default path configured into
1515
	If @var{dir} is NULL, the search will take place starting at
1479
	libbfd at build time.  [XXX this feature is not currently
1516
	the current directory.
1480
	implemented].
1481
1517
1482
RETURNS
1518
RETURNS
1483
	<<NULL>> on any errors or failure to locate the .debug file,
1519
	<<NULL>> on any errors or failure to locate the .debug file,
Lines 1488-1494 RETURNS Link Here
1488
char *
1524
char *
1489
bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
1525
bfd_follow_gnu_debuglink (bfd *abfd, const char *dir)
1490
{
1526
{
1491
  return find_separate_debug_file (abfd, dir,
1527
  return find_separate_debug_file (abfd, dir, TRUE,
1492
				   bfd_get_debug_link_info,
1528
				   bfd_get_debug_link_info,
1493
				   separate_debug_file_exists);
1529
				   separate_debug_file_exists);
1494
}
1530
}
Lines 1522-1535 DESCRIPTION Link Here
1522
1558
1523
	Takes a BFD and searches it for a .gnu_debugaltlink section.  If this
1559
	Takes a BFD and searches it for a .gnu_debugaltlink section.  If this
1524
	section is found, it examines the section for the name of a file
1560
	section is found, it examines the section for the name of a file
1525
	containing auxiliary debugging information.  It	then searches the
1561
	containing auxiliary debugging information.  It then searches the
1526
	filesystem for this file in a set of standard locations, including
1562
	filesystem for this file in a set of standard locations, including
1527
	the directory tree rooted at @var{dir}, and if found returns the
1563
	the directory tree rooted at @var{dir}, and if found returns the
1528
	full filename.
1564
	full filename.
1529
1565
1530
	If @var{dir} is NULL, it will search a default path configured into
1566
	If @var{dir} is NULL, the search will take place starting at
1531
	libbfd at build time.  [FIXME: This feature is not currently
1567
	the current directory.
1532
	implemented].
1533
1568
1534
RETURNS
1569
RETURNS
1535
	<<NULL>> on any errors or failure to locate the debug file,
1570
	<<NULL>> on any errors or failure to locate the debug file,
Lines 1540-1546 RETURNS Link Here
1540
char *
1575
char *
1541
bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
1576
bfd_follow_gnu_debugaltlink (bfd *abfd, const char *dir)
1542
{
1577
{
1543
  return find_separate_debug_file (abfd, dir,
1578
  return find_separate_debug_file (abfd, dir, TRUE,
1544
				   get_alt_debug_link_info_shim,
1579
				   get_alt_debug_link_info_shim,
1545
				   separate_alt_debug_file_exists);
1580
				   separate_alt_debug_file_exists);
1546
}
1581
}
Lines 1695-1697 bfd_fill_in_gnu_debuglink_section (bfd *abfd, Link Here
1695
1730
1696
  return TRUE;
1731
  return TRUE;
1697
}
1732
}
1733
1734
1735
static char *
1736
get_build_id_name (bfd *abfd, unsigned long *build_id_out)
1737
{
1738
  struct bfd_build_id *build_id;
1739
  char *name;
1740
  char *n;
1741
  bfd_size_type s;
1742
  bfd_byte *d;
1743
1744
  if (abfd == NULL || abfd->filename == NULL || build_id_out == NULL)
1745
    {
1746
      bfd_set_error (bfd_error_invalid_operation);
1747
      return NULL;
1748
    }
1749
1750
  if (abfd->build_id && abfd->build_id->size > 0)
1751
    {
1752
      /* Save some time by using the already computed build-id.
1753
	 FIXME: Is this safe/reliable ?  */
1754
      build_id = (struct bfd_build_id *) abfd->build_id;
1755
    }
1756
  else
1757
    {
1758
      Elf_Internal_Note inote;
1759
      Elf_External_Note *enote;
1760
      bfd_byte *contents;
1761
      asection *sect;
1762
1763
      sect = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
1764
      if (sect == NULL)
1765
	{
1766
	  bfd_set_error (bfd_error_no_debug_section);
1767
	  return NULL;
1768
	}
1769
1770
      /* FIXME: Should we support smaller build-id notes ?  */
1771
      if (bfd_get_section_size (sect) < 0x24)
1772
	{
1773
	  bfd_set_error (bfd_error_invalid_operation);
1774
	  return NULL;
1775
	}
1776
1777
      if (!bfd_malloc_and_get_section (abfd, sect, & contents))
1778
	{
1779
	  if (contents != NULL)
1780
	    free (contents);
1781
	  return NULL;
1782
	}
1783
1784
      enote = (Elf_External_Note *) contents;
1785
      inote.type = H_GET_32 (abfd, enote->type);
1786
      inote.namesz = H_GET_32 (abfd, enote->namesz);
1787
      inote.namedata = enote->name;
1788
      inote.descsz = H_GET_32 (abfd, enote->descsz);
1789
      inote.descdata = inote.namedata + BFD_ALIGN (inote.namesz, 4);
1790
      /* FIXME: Should we check for extra notes in this section ?  */
1791
	  
1792
      if (inote.descsz == 0
1793
	  || inote.type != NT_GNU_BUILD_ID
1794
	  || inote.namesz != 4 /* sizeof "GNU"  */
1795
	  || strcmp (inote.namedata, "GNU") != 0)
1796
	{
1797
	  free (contents);
1798
	  bfd_set_error (bfd_error_invalid_operation);
1799
	  return NULL;
1800
	}
1801
1802
      build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) + inote.descsz);
1803
      if (build_id == NULL)
1804
	{
1805
	  free (contents);
1806
	  return NULL;
1807
	}
1808
1809
      build_id->size = inote.descsz;
1810
      memcpy (build_id->data, inote.descdata, inote.descsz);
1811
      abfd->build_id = build_id;
1812
      free (contents);
1813
    }
1814
1815
  /* Compute the debug pathname corresponding to the build-id.  */
1816
  name = bfd_malloc (strlen (".build-id/") + build_id->size * 2 + 2 + strlen (".debug"));
1817
  if (name == NULL)
1818
    {
1819
      bfd_set_error (bfd_error_no_memory);
1820
      return NULL;
1821
    }
1822
  n = name;
1823
  d = build_id->data;
1824
  s = build_id->size;
1825
1826
  n += sprintf (n, ".build-id/");
1827
  n += sprintf (n, "%02x", (unsigned) *d++); s--;
1828
  n += sprintf (n, "/");
1829
  while (s--)
1830
    n += sprintf (n, "%02x", (unsigned) *d++);
1831
  n += sprintf (n, ".debug");
1832
1833
  * build_id_out = (unsigned long) build_id;
1834
  return name;
1835
}
1836
1837
/*
1838
FUNCTION
1839
	bfd_follow_build_id_debuglink
1840
1841
SYNOPSIS
1842
	char *bfd_follow_build_id_debuglink (bfd *abfd, const char *dir);
1843
1844
DESCRIPTION
1845
1846
	Takes @var{abfd} and searches it for a .note.gnu.build-id section.
1847
	If this section is found, it extracts the value of the NT_GNU_BUILD_ID
1848
	note, which should be a hexadecimal value @var{NNNN+NN} (for
1849
	32+ hex digits).  It then searches the filesystem for a file named
1850
	@var{.build-id/NN/NN+NN.debug} in a set of standard locations,
1851
	including the directory tree rooted at @var{dir}.  The filename
1852
	of the first matching file to be found is returned.  A matching
1853
	file should contain a .note.gnu.build-id section with the same
1854
	@var{NNNN+NN} note as @var{abfd}, although this check is currently
1855
	not implemented.
1856
1857
	If @var{dir} is NULL, the search will take place starting at
1858
	the current directory.
1859
1860
RETURNS
1861
	<<NULL>> on any errors or failure to locate the debug file,
1862
	otherwise a pointer to a heap-allocated string containing the
1863
	filename.  The caller is responsible for freeing this string.
1864
*/
1865
1866
char *
1867
bfd_follow_build_id_debuglink (bfd *abfd, const char *dir)
1868
{
1869
  return find_separate_debug_file (abfd, dir, FALSE,
1870
				   get_build_id_name,
1871
	   /* FIXME: Replace with a function that checks the build-id ?  */
1872
				   separate_alt_debug_file_exists);
1873
}
(-)a/binutils/testsuite/binutils-all/objdump.exp (+80 lines)
Lines 273-278 if { ![is_elf_format] } then { Link Here
273
    }
273
    }
274
}
274
}
275
275
276
proc test_build_id_debuglink {} {
277
    global srcdir
278
    global subdir
279
    global env
280
    global CC_FOR_TARGET
281
    global STRIP
282
    global OBJCOPY
283
    global OBJDUMP
284
    global CFLAGS_FOR_TARGET
285
    
286
    set test "build-id-debuglink"
287
    if {![info exists CC_FOR_TARGET]} {
288
	set CC_FOR_TARGET $env(CC)
289
    }
290
    if { $CC_FOR_TARGET == "" } {
291
	unsupported $test
292
	return
293
    }
294
295
    # Use a fixed build-id.
296
    set CFLAGS_FOR_TARGET "-g -Wl,--build-id=0x12345678abcdef01"
297
298
    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog exectuable debug] != "" } {
299
	fail "$test (build)"
300
	return
301
    }
302
303
    # FIXME: Do we need to restore CFLAGS_FOR_TARGET to its old value ?
304
305
    if { [binutils_run $STRIP "--strip-debug --remove-section=.comment tmpdir/testprog -o tmpdir/testprog.strip"] != "" } {
306
	fail "$test (strip debug info)"
307
	return
308
    }
309
310
    if { [binutils_run $OBJCOPY "--only-keep-debug tmpdir/testprog tmpdir/testprog.debug"] != "" } {
311
	fail "$test (create separate debug info file)"
312
	return
313
    }
314
315
    set got [remote_exec host "mkdir -p .build-id/12" ]
316
    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
317
	fail "$test (make debug directory)"
318
	return
319
    }
320
321
    set got [remote_exec host "cp tmpdir/testprog.debug .build-id/12/345678abcdef01.debug"]
322
    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
323
	fail "$test (copy debug info into debug directory)"
324
	return
325
    }
326
    
327
    set got [remote_exec host "$OBJDUMP -Sl tmpdir/testprog.strip" "" "/dev/null" "tmpdir/testprog.strip.dump"]
328
    if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
329
	fail "$test (post strip dump)"
330
	return
331
    }
332
333
    set src2 tmpdir/testprog.strip.dump
334
    verbose " grep -e testprog.c ${src2}"
335
    set status [remote_exec build grep "-e testprog.c ${src2}"]
336
    set exec_output [lindex $status 1]
337
    set exec_output [prune_warnings $exec_output]
338
    if [string match "" $exec_output] then {
339
	send_log "$exec_output\n"
340
	verbose "$exec_output" 1
341
	fail "$test (grepping for source file name in disassembly output)"
342
    } else {
343
	pass "$test"
344
	# Cleanup...
345
	set got [remote_exec host "rm .build-id/12/345678abcdef01.debug"]
346
	set got [remote_exec host "rmdir -p .build-id/12" ]
347
	set got [remote_exec host "rm tmpdir/testprog.strip.dump"]
348
	set got [remote_exec host "rm tmpdir/testprog.debug"]
349
	set got [remote_exec host "rm tmpdir/testprog.strip"]
350
    }
351
}
352
353
if {[isnative] && [is_elf_format]} then {
354
    test_build_id_debuglink
355
}
276
356
277
# Options which are not tested: -a -d -D -R -T -x -l --stabs
357
# Options which are not tested: -a -d -D -R -T -x -l --stabs
278
# I don't see any generic way to test any of these other than -a.
358
# I don't see any generic way to test any of these other than -a.

Return to bug 20876