Subject: long name ar fix to NetBSD-current (and probably FreeBSD, too) linker
To: None <current-users@sun-lamp.cs.berkeley.edu, freebsd-hackers@freefall.cdrom.com,>
From: Bill Sommerfeld <sommerfeld@orchard.medford.ma.us>
List: current-users
Date: 11/28/1993 22:27:15
The following patch to NetBSD-current ld/lib.c causes it to correctly
handle archive member names longer than OLDARMAXNAME (15) characters
long; without this behavior, ld reports "bad magic number" when it
tries to bring in a file with a long name from an archive.
As Mark Eichin recently reported, this is a long-standing bug in *BSD,
dating back to 386BSD 0.0, which, among other things, breaks the build
of Kerberos.
This bug likely also exists under FreeBSD.
This has been tested by rebuilding libc.a, libc_p.a, libc_pic.a, and
libc.so.1.1 without the `T' option to ar, as well as with a smaller
test case of a library containing a file named
"funkelhausersteinweitz.o".
Once you install and verify this change, you should also edit
src/share/bsd.lib.mk to change all occurances of "cTq" to "cq", and
reinstall it, then rebuild all archive libraries which contain
truncated object file names.
- Bill
*** 1.1 1993/11/29 02:32:13
--- 1.2 1993/11/29 03:00:12
***************
*** 78,88 ****
{
int bytes_read;
register int namelen;
! int member_length;
register char *name;
struct ar_hdr hdr1;
register struct file_entry *subentry;
!
lseek(desc, subfile_offset, 0);
bytes_read = read(desc, &hdr1, sizeof hdr1);
--- 78,88 ----
{
int bytes_read;
register int namelen;
! int member_length, content_length;
register char *name;
struct ar_hdr hdr1;
register struct file_entry *subentry;
! int starting_offset;
lseek(desc, subfile_offset, 0);
bytes_read = read(desc, &hdr1, sizeof hdr1);
***************
*** 104,125 ****
&& hdr1.ar_name[namelen] != '/';
namelen++);
! name = (char *) xmalloc(namelen + 1);
! strncpy(name, hdr1.ar_name, namelen);
! name[namelen] = 0;
!
subentry->filename = name;
subentry->local_sym_name = name;
subentry->symbols = 0;
subentry->strings = 0;
subentry->subfiles = 0;
! subentry->starting_offset = subfile_offset + sizeof hdr1;
subentry->superfile = library_entry;
subentry->library_flag = 0;
subentry->header_read_flag = 0;
subentry->just_syms_flag = 0;
subentry->chain = 0;
! subentry->total_size = member_length;
(*length_loc) = member_length;
--- 104,147 ----
&& hdr1.ar_name[namelen] != '/';
namelen++);
! starting_offset = subfile_offset + sizeof hdr1;
! content_length = member_length;
! #ifdef AR_EFMT1
! /*
! * BSD 4.4 extended AR format: #1/<namelen>, with name as the
! * first <namelen> bytes of the file
! */
! if ((hdr1.ar_name[0]=='#') &&
! (hdr1.ar_name[1]=='1') &&
! (hdr1.ar_name[2]=='/') &&
! (isdigit(hdr1.ar_name[3])))
! {
! namelen = atoi (&hdr1.ar_name[3]);
! name = (char *) xmalloc(namelen + 1);
! read (desc, name, namelen);
! name[namelen] = 0;
! content_length -= namelen;
! starting_offset += namelen;
! } else
! #endif
! {
! name = (char *) xmalloc(namelen + 1);
! strncpy(name, hdr1.ar_name, namelen);
! name[namelen] = 0;
! }
!
subentry->filename = name;
subentry->local_sym_name = name;
subentry->symbols = 0;
subentry->strings = 0;
subentry->subfiles = 0;
! subentry->starting_offset = starting_offset;
subentry->superfile = library_entry;
subentry->library_flag = 0;
subentry->header_read_flag = 0;
subentry->just_syms_flag = 0;
subentry->chain = 0;
! subentry->total_size = content_length;
(*length_loc) = member_length;
------------------------------------------------------------------------------