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 + <> is returned if all is ok, otherwise <>. + */ + + 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, ×tamp); 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 <> 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 + <> is returned if all is ok. Otherwise <> 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);