Re: separated debuginfo patch

Philippe Elie
2003-07-04T23:40:55Z

[-- Attachment #1: Type: text/plain, Size: 111 bytes --]

Philippe Elie wrote:
> Nick Clifton wrote:
>
>> Hi Philippe,
>

sorry, the missing patch ...

regards,
Phil

[-- Attachment #2: bfd.diff --]
[-- Type: text/plain, Size: 14208 bytes --]

Index: bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.226
diff -c -3 -p -r1.226 bfd-in2.h
*** bfd-in2.h 1 Jul 2003 14:44:59 -0000 1.226
--- bfd-in2.h 4 Jul 2003 21:18:00 -0000
*************** bfd_boolean bfd_make_readable (bfd *abfd
*** 853,865 ****
unsigned long bfd_calc_gnu_debuglink_crc32
(unsigned long crc, const unsigned char *buf, bfd_size_type len);

char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);

struct sec *bfd_create_gnu_debuglink_section
(bfd *abfd, const char *filename);

bfd_boolean bfd_fill_in_gnu_debuglink_section
! (bfd *abfd, struct sec *sect, const char *filename);

/* Extracted from libbfd.c. */

--- 853,874 ----
unsigned long bfd_calc_gnu_debuglink_crc32
(unsigned long crc, const unsigned char *buf, bfd_size_type len);

+ char *bfd_get_debug_link_info
+ (bfd *abfd, unsigned long *crc32_out, unsigned long *timestamp);
+
char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir);

struct sec *bfd_create_gnu_debuglink_section
(bfd *abfd, const char *filename);

bfd_boolean bfd_fill_in_gnu_debuglink_section
! (bfd *abfd, struct sec *sect, const char *filename,
! unsigned long timestamp);
!
! struct sec *bfd_create_gnu_debuglink_timestamp_section (bfd *abfd);
!
! bfd_boolean bfd_fill_in_gnu_debuglink_timestamp_section
! (bfd *abfd, struct sec *sect, unsigned long timestamp);

/* Extracted from libbfd.c. */

Index: opncls.c
===================================================================
RCS file: /cvs/src/src/bfd/opncls.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 opncls.c
*** opncls.c 29 Jun 2003 10:06:39 -0000 1.18
--- opncls.c 4 Jul 2003 21:18:02 -0000
*************** bfd_release (bfd *abfd, void *block)
*** 692,697 ****
--- 692,698 ----
*/

#define GNU_DEBUGLINK ".gnu_debuglink"
+ #define GNU_DEBUGLINK_TIMESTAMP ".gnu_debuglink_timestamp"
/*
FUNCTION
bfd_calc_gnu_debuglink_crc32
*************** bfd_calc_gnu_debuglink_crc32 (unsigned l
*** 779,798 ****

/*
! INTERNAL_FUNCTION
! get_debug_link_info

SYNOPSIS
! char *get_debug_link_info (bfd *abfd, unsigned long *crc32_out);

DESCRIPTION
! fetch the filename and CRC32 value for any separate debuginfo
! associated with @var{abfd}. Return NULL if no such info found,
! otherwise return filename and update @var{crc32_out}.
*/

! static char *
! get_debug_link_info (bfd *abfd, unsigned long *crc32_out)
{
asection * sect;
bfd_size_type debuglink_size;
--- 780,803 ----

/*
! FUNCTION
! bfd_get_debug_link_info

SYNOPSIS
! char *bfd_get_debug_link_info
! (bfd *abfd, unsigned long *crc32_out, unsigned long *timestamp);

DESCRIPTION
! fetch the filename, CRC32 value and 32 bits timestamp for any
! separate debuginfo associated with @var{abfd}. Return NULL if no such
! info found, otherwise return filename, update @var{crc32_out} and
! @var{timestamp}. If timestamp is not available return 0 in
! @var{timestamp}
*/

! char *
! bfd_get_debug_link_info (bfd *abfd, unsigned long *crc32_out,
! unsigned long *timestamp)
{
asection * sect;
bfd_size_type debuglink_size;
*************** get_debug_link_info (bfd *abfd, unsigned
*** 803,808 ****
--- 808,814 ----

BFD_ASSERT (abfd);
BFD_ASSERT (crc32_out);
+ BFD_ASSERT (timestamp);

sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK);

*************** get_debug_link_info (bfd *abfd, unsigned
*** 828,852 ****

crc32 = bfd_get_32 (abfd, contents + crc_offset);

*crc32_out = crc32;
return contents;
}

/*
INTERNAL_FUNCTION
separate_debug_file_exists

SYNOPSIS
bfd_boolean separate_debug_file_exists
! (char *name, unsigned long crc32);

DESCRIPTION
Checks to see if @var{name} is a file and if its contents
! match @var{crc32}.
*/

static bfd_boolean
! separate_debug_file_exists (const char *name, const unsigned long crc)
{
static char buffer [8 * 1024];
unsigned long file_crc = 0;
--- 834,920 ----

crc32 = bfd_get_32 (abfd, contents + crc_offset);

+ /* .gnu_debuglink format changed by adding a timestamp value after the
+ * the crc, we must support the old format */
+ *timestamp = 0;
+ if (debuglink_size - (crc_offset + 4) >= 4)
+ *timestamp = bfd_get_32 (abfd, contents + crc_offset + 4);
+
*crc32_out = crc32;
return contents;
}

/*
INTERNAL_FUNCTION
+ bfd_get_debug_timestamp_info
+
+ SYNOPSIS
+ bfd_boolean bfd_get_debug_timestamp_info
+ (bfd *abfd, unsigned long *timestamp);
+
+ DESCRIPTION
+ fetch the timestamp for any separate debuginfo associated with
+ @var{abfd}.
+
+ RETURNS
+ <<TRUE>> is returned if all is ok, otherwise <<FALSE>>.
+ */
+
+ static bfd_boolean
+ bfd_get_debug_timestamp_info (bfd *abfd, unsigned long *timestamp)
+ {
+ asection * sect;
+ bfd_size_type timestamp_size;
+ bfd_boolean ret;
+ char * contents;
+
+ BFD_ASSERT (abfd);
+ BFD_ASSERT (timestamp);
+
+ sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK_TIMESTAMP);
+
+ if (sect == NULL)
+ return FALSE;
+
+ timestamp_size = bfd_section_size (abfd, sect);
+
+ if (timestamp_size != 4)
+ return FALSE;
+
+ contents = malloc (timestamp_size);
+ if (contents == NULL)
+ return FALSE;
+
+ ret = bfd_get_section_contents (abfd, sect, contents, 0, timestamp_size);
+ if (! ret)
+ {
+ free (contents);
+ return FALSE;
+ }
+
+ *timestamp = bfd_get_32 (abfd, contents);
+
+ free (contents);
+
+ return TRUE;
+ }
+
+ /*
+ INTERNAL_FUNCTION
separate_debug_file_exists

SYNOPSIS
bfd_boolean separate_debug_file_exists
! (char *name, unsigned long crc32, unsigned long timestamp);

DESCRIPTION
Checks to see if @var{name} is a file and if its contents
! match @var{timestamp} or if the @var{crc32} match.
*/

static bfd_boolean
! separate_debug_file_exists (const char *name, const unsigned long crc,
! unsigned long timestamp)
{
static char buffer [8 * 1024];
unsigned long file_crc = 0;
*************** separate_debug_file_exists (const char *
*** 855,860 ****
--- 923,954 ----

BFD_ASSERT (name);

+ printf("try %s %ld\n", name, timestamp);
+
+ if (timestamp)
+ {
+ bfd *abfd = bfd_openr(name, NULL);
+
+ if (abfd)
+ {
+ char ** matching;
+
+ if (bfd_check_format_matches(abfd, bfd_object, &matching))
+ {
+ unsigned long temp_timestamp;
+
+ if (bfd_get_debug_timestamp_info (abfd, &temp_timestamp))
+ {
+ bfd_close(abfd);
+ return temp_timestamp == timestamp;
+ }
+ bfd_close (abfd);
+ }
+ }
+ }
+
+ printf("doing full crc\n");
+
fd = open (name, O_RDONLY);
if (fd < 0)
return FALSE;
*************** find_separate_debug_file (bfd *abfd, con
*** 891,896 ****
--- 985,991 ----
char *dir;
char *debugfile;
unsigned long crc32;
+ unsigned long timestamp;
int i;

BFD_ASSERT (abfd);
*************** find_separate_debug_file (bfd *abfd, con
*** 901,907 ****
if (! abfd->filename)
return NULL;

! basename = get_debug_link_info (abfd, & crc32);
if (basename == NULL)
return NULL;

--- 996,1002 ----
if (! abfd->filename)
return NULL;

! basename = bfd_get_debug_link_info (abfd, &crc32, &timestamp);
if (basename == NULL)
return NULL;

*************** find_separate_debug_file (bfd *abfd, con
*** 943,949 ****
strcpy (debugfile, dir);
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32))
{
free (basename);
free (dir);
--- 1038,1044 ----
strcpy (debugfile, dir);
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32, timestamp))
{
free (basename);
free (dir);
*************** find_separate_debug_file (bfd *abfd, con
*** 955,961 ****
strcat (debugfile, ".debug/");
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32))
{
free (basename);
free (dir);
--- 1050,1056 ----
strcat (debugfile, ".debug/");
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32, timestamp))
{
free (basename);
free (dir);
*************** find_separate_debug_file (bfd *abfd, con
*** 972,978 ****
strcat (debugfile, dir);
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32))
{
free (basename);
free (dir);
--- 1067,1073 ----
strcat (debugfile, dir);
strcat (debugfile, basename);

! if (separate_debug_file_exists (debugfile, crc32, timestamp))
{
free (basename);
free (dir);
*************** bfd_create_gnu_debuglink_section (bfd *a
*** 1073,1079 ****
debuglink_size = strlen (filename) + 1;
debuglink_size += 3;
debuglink_size &= ~3;
! debuglink_size += 4;

if (! bfd_set_section_size (abfd, sect, debuglink_size))
/* XXX Should we delete the section from the bfd ? */
--- 1168,1174 ----
debuglink_size = strlen (filename) + 1;
debuglink_size += 3;
debuglink_size &= ~3;
! debuglink_size += 8;

if (! bfd_set_section_size (abfd, sect, debuglink_size))
/* XXX Should we delete the section from the bfd ? */
*************** FUNCTION
*** 1089,1095 ****

SYNOPSIS
bfd_boolean bfd_fill_in_gnu_debuglink_section
! (bfd *abfd, struct sec *sect, const char *filename);

DESCRIPTION

--- 1184,1191 ----

SYNOPSIS
bfd_boolean bfd_fill_in_gnu_debuglink_section
! (bfd *abfd, struct sec *sect, const char *filename,
! unsigned long timestamp);

DESCRIPTION

*************** RETURNS
*** 1106,1112 ****
bfd_boolean
bfd_fill_in_gnu_debuglink_section (bfd *abfd,
struct sec *sect,
! const char *filename)
{
bfd_size_type debuglink_size;
unsigned long crc32;
--- 1202,1209 ----
bfd_boolean
bfd_fill_in_gnu_debuglink_section (bfd *abfd,
struct sec *sect,
! const char *filename,
! unsigned long timestamp)
{
bfd_size_type debuglink_size;
unsigned long crc32;
*************** bfd_fill_in_gnu_debuglink_section (bfd *
*** 1147,1153 ****
debuglink_size = strlen (filename) + 1;
debuglink_size += 3;
debuglink_size &= ~3;
! debuglink_size += 4;

contents = malloc (debuglink_size);
if (contents == NULL)
--- 1244,1250 ----
debuglink_size = strlen (filename) + 1;
debuglink_size += 3;
debuglink_size &= ~3;
! debuglink_size += 8;

contents = malloc (debuglink_size);
if (contents == NULL)
*************** bfd_fill_in_gnu_debuglink_section (bfd *
*** 1158,1168 ****
}

strcpy (contents, filename);
! crc_offset = debuglink_size - 4;

bfd_put_32 (abfd, crc32, contents + crc_offset);

if (! bfd_set_section_contents (abfd, sect, contents, 0, debuglink_size))
{
/* XXX Should we delete the section from the bfd ? */
free (contents);
--- 1255,1373 ----
}

strcpy (contents, filename);
! crc_offset = debuglink_size - 8;

bfd_put_32 (abfd, crc32, contents + crc_offset);
+ bfd_put_32 (abfd, timestamp, contents + crc_offset + 4);

if (! bfd_set_section_contents (abfd, sect, contents, 0, debuglink_size))
+ {
+ /* XXX Should we delete the section from the bfd ? */
+ free (contents);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*
+ FUNCTION
+ bfd_create_gnu_debuglink_timestamp_section
+
+ SYNOPSIS
+ struct sec *bfd_create_gnu_debuglink_timestamp_section (bfd *abfd);
+
+ DESCRIPTION
+
+ Takes a @var{BFD} and adds a .gnu_debuglink_time_stamp section to it.
+ The section is sized to be big enough to contain a 32 bits timestamp
+ value.
+
+ RETURNS
+ A pointer to the new section is returned if all is ok. Otherwise <<NULL>> is
+ returned and bfd_error is set.
+ */
+
+ asection *
+ bfd_create_gnu_debuglink_timestamp_section (bfd *abfd)
+ {
+ asection *sect;
+
+ if (abfd == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK_TIMESTAMP);
+ if (sect)
+ {
+ /* Section already exists. */
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ sect = bfd_make_section (abfd, GNU_DEBUGLINK_TIMESTAMP);
+ if (sect == NULL)
+ return NULL;
+
+ if (! bfd_set_section_flags (abfd, sect,
+ SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING))
+ /* XXX Should we delete the section from the bfd ? */
+ return NULL;
+
+
+ if (! bfd_set_section_size (abfd, sect, 4))
+ /* XXX Should we delete the section from the bfd ? */
+ return NULL;
+
+ return sect;
+ }
+
+
+ /*
+ FUNCTION
+ bfd_fill_in_gnu_debuglink_timestamp_section
+
+ SYNOPSIS
+ bfd_boolean bfd_fill_in_gnu_debuglink_timestamp_section
+ (bfd *abfd, struct sec *sect, unsigned long timestamp);
+
+ DESCRIPTION
+
+ Takes a @var{BFD} and containing a .gnu_debuglink section @var{SECT}
+ and fills in the contents of the section to contain a link to the
+ specified @var{filename}. The filename should be relative to the
+ current directory.
+
+ RETURNS
+ <<TRUE>> is returned if all is ok. Otherwise <<FALSE>> is returned
+ and bfd_error is set.
+ */
+
+ bfd_boolean
+ bfd_fill_in_gnu_debuglink_timestamp_section (bfd *abfd, struct sec *sect,
+ unsigned long timestamp)
+ {
+ char * contents;
+
+ if (abfd == NULL || sect == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
+ contents = malloc (4);
+ if (contents == NULL)
+ {
+ /* XXX Should we delete the section from the bfd ? */
+ bfd_set_error (bfd_error_no_memory);
+ return FALSE;
+ }
+
+ bfd_put_32 (abfd, timestamp, contents);
+
+ if (! bfd_set_section_contents (abfd, sect, contents, 0, 4))
{
/* XXX Should we delete the section from the bfd ? */
free (contents);

[-- Attachment #3: binutils.diff --]
[-- Type: text/plain, Size: 3871 bytes --]

Index: objcopy.c
===================================================================
RCS file: /cvs/src/src/binutils/objcopy.c,v
retrieving revision 1.51
diff -c -3 -p -r1.51 objcopy.c
*** objcopy.c 27 Jun 2003 08:01:28 -0000 1.51
--- objcopy.c 4 Jul 2003 21:18:19 -0000
*************** static struct section_add *add_sections;
*** 224,229 ****
--- 224,233 ----
This should be the filename to store in the .gnu_debuglink section. */
static const char * gnu_debuglink_filename = NULL;

+ /* If non zero the argument to --set-debuglink-timestamp.
+ This should be the value to store in the .gnu_debuglink_timestamp */
+ static unsigned long int gnu_debuglink_timestamp;
+
/* Whether to convert debugging information. */
static bfd_boolean convert_debugging = FALSE;

*************** static char *prefix_alloc_sections_strin
*** 286,291 ****
--- 290,296 ----
#define OPTION_FORMATS_INFO (OPTION_PREFIX_ALLOC_SECTIONS + 1)
#define OPTION_ADD_GNU_DEBUGLINK (OPTION_FORMATS_INFO + 1)
#define OPTION_ONLY_KEEP_DEBUG (OPTION_ADD_GNU_DEBUGLINK + 1)
+ #define OPTION_SET_DEBUGLINK_TIMESTAMP (OPTION_ONLY_KEEP_DEBUG + 1)

/* Options to handle if running as "strip". */

*************** static struct option copy_options[] =
*** 371,376 ****
--- 376,382 ----
{"set-start", required_argument, 0, OPTION_SET_START},
{"srec-len", required_argument, 0, OPTION_SREC_LEN},
{"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
+ {"set-debuglink-timestamp", required_argument, 0, OPTION_SET_DEBUGLINK_TIMESTAMP},
{"strip-all", no_argument, 0, 'S'},
{"strip-debug", no_argument, 0, 'g'},
{"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
*************** copy_object (ibfd, obfd)
*** 1133,1138 ****
--- 1139,1145 ----
long symcount;
asection **osections = NULL;
asection * gnu_debuglink_section = NULL;
+ asection * gnu_debuglink_timestamp_section = NULL;
bfd_size_type *gaps = NULL;
bfd_size_type max_gap = 0;
long symsize;
*************** copy_object (ibfd, obfd)
*** 1258,1263 ****
--- 1265,1280 ----
RETURN_NONFATAL (gnu_debuglink_filename);
}
}
+ else if (gnu_debuglink_timestamp) {
+ gnu_debuglink_timestamp_section =
+ bfd_create_gnu_debuglink_timestamp_section (obfd);
+
+ if (gnu_debuglink_timestamp_section == NULL)
+ {
+ fprintf (stderr, "UGG A\n");
+ RETURN_NONFATAL ("Unable to create gnu_debuglink_timestamp section");
+ }
+ }

if (gap_fill_set || pad_to_set)
{
*************** copy_object (ibfd, obfd)
*** 1421,1434 ****

if (gnu_debuglink_filename != NULL)
{
! if (! bfd_fill_in_gnu_debuglink_section
! (obfd, gnu_debuglink_section, gnu_debuglink_filename))
{
fprintf (stderr, "UGG 2\n");
RETURN_NONFATAL (gnu_debuglink_filename);
}
}

if (gap_fill_set || pad_to_set)
{
bfd_byte *buf;
--- 1438,1462 ----

if (gnu_debuglink_filename != NULL)
{
! if (! bfd_fill_in_gnu_debuglink_section (obfd, gnu_debuglink_section,
! gnu_debuglink_filename,
! gnu_debuglink_timestamp))
{
fprintf (stderr, "UGG 2\n");
RETURN_NONFATAL (gnu_debuglink_filename);
}
}

+ if (gnu_debuglink_timestamp_section)
+ {
+ if (! bfd_fill_in_gnu_debuglink_timestamp_section
+ (obfd, gnu_debuglink_timestamp_section, gnu_debuglink_timestamp))
+ {
+ fprintf (stderr, "UGG 3\n");
+ RETURN_NONFATAL ("Unable to fill gnu_debuglink_timestamp section");
+ }
+ }
+
if (gap_fill_set || pad_to_set)
{
bfd_byte *buf;
*************** copy_main (argc, argv)
*** 2458,2463 ****
--- 2486,2495 ----

case OPTION_ADD_GNU_DEBUGLINK:
gnu_debuglink_filename = optarg;
+ break;
+
+ case OPTION_SET_DEBUGLINK_TIMESTAMP:
+ gnu_debuglink_timestamp = atoi(optarg);
break;

case 'K':

[-- Attachment #4: gdb.diff --]
[-- Type: text/plain, Size: 665 bytes --]

Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.101
diff -u -r1.101 symfile.c
--- symfile.c 27 Jun 2003 13:11:17 -0000 1.101
+++ symfile.c 3 Jul 2003 13:54:51 -0000
@@ -1103,6 +1103,7 @@
static char *
find_separate_debug_file (struct objfile *objfile)
{
+#if 0
asection *sect;
char *basename;
char *dir;
@@ -1178,6 +1179,12 @@
xfree (basename);
xfree (dir);
return NULL;
+#else
+ char *debug_file = NULL;
+ if (objfile->obfd)
+ debug_file = bfd_follow_gnu_debuglink(objfile->obfd, debug_file_directory);
+ return debug_file;
+#endif
}