svn commit: r346902 - stable/12/usr.bin/ar
Ed Maste
emaste at FreeBSD.org
Mon Apr 29 18:34:13 UTC 2019
Author: emaste
Date: Mon Apr 29 18:34:11 2019
New Revision: 346902
URL: https://svnweb.freebsd.org/changeset/base/346902
Log:
MFC ar: implement support for /SYM64/ 64-bit archives
r346079: ar: implement support for /SYM64/ 64-bit archives
Submitted by: Gerald Aryeetey <aryeeteygerald_rogers.com>
Reviewed by: imp (earlier)
r346568: ar: test for writing 64-bit format only if symbol count is nonzero
This is a minor simplification; if we do not have any symbols the empty
symbol table can be in 32-bit format.
r346569: ar: use array notation to access s_so
This is somewhat more readable than pointer arithmetic. Also remove an
unnecessary cast while here.
r346582: ar: shuffle symbol offsets during conversion for 32-bit ar archives
During processing we maintain symbol offsets in the 64-bit s_so array,
and when writing the archive convert to 32-bit if no offsets are greater
than 4GB. However, this was somewhat inefficient as we looped over the
array twice: first, converting to big endian and second, writing each
32-bit value one at a time (and incorrectly so on big-endian platforms).
Instead, when writing a 32-bit archive shuffle convert symbol data to
big endian (as required by the ar format) and shuffle to the beginning
of the allocation at the same time.
Also correct emission of the symbol count on big endian platforms.
Further changes are planned, but this should fix powerpc64.
Reported by: jhibbits, mlinimon
Reviewed by: jhibbits, Gerald Aryeetey (earlier)
Tested by: jhibbits
PR: 234454
Sponsored by: The FreeBSD Foundation
Modified:
stable/12/usr.bin/ar/ar.h
stable/12/usr.bin/ar/read.c
stable/12/usr.bin/ar/write.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/usr.bin/ar/ar.h
==============================================================================
--- stable/12/usr.bin/ar/ar.h Mon Apr 29 18:28:34 2019 (r346901)
+++ stable/12/usr.bin/ar/ar.h Mon Apr 29 18:34:11 2019 (r346902)
@@ -100,9 +100,11 @@ struct bsdar {
/*
* Fields for the archive symbol table.
*/
- uint32_t s_cnt; /* current number of symbols. */
- uint32_t *s_so; /* symbol offset table. */
+ uint64_t s_cnt; /* current number of symbols. */
+ uint64_t *s_so; /* symbol offset table. */
+ uint64_t s_so_max; /* maximum symbol offset. */
size_t s_so_cap; /* capacity of so table buffer. */
+
char *s_sn; /* symbol name table */
size_t s_sn_cap; /* capacity of sn table buffer. */
size_t s_sn_sz; /* current size of sn table. */
Modified: stable/12/usr.bin/ar/read.c
==============================================================================
--- stable/12/usr.bin/ar/read.c Mon Apr 29 18:28:34 2019 (r346901)
+++ stable/12/usr.bin/ar/read.c Mon Apr 29 18:34:11 2019 (r346902)
@@ -109,7 +109,8 @@ read_archive(struct bsdar *bsdar, char mode)
break;
/* Skip pseudo members. */
- if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0)
+ if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0 ||
+ strcmp(name, "/SYM64/") == 0)
continue;
if (bsdar->argc > 0) {
Modified: stable/12/usr.bin/ar/write.c
==============================================================================
--- stable/12/usr.bin/ar/write.c Mon Apr 29 18:28:34 2019 (r346901)
+++ stable/12/usr.bin/ar/write.c Mon Apr 29 18:34:11 2019 (r346902)
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#define _ARMAG_LEN 8 /* length of ar magic string */
#define _ARHDR_LEN 60 /* length of ar header */
#define _INIT_AS_CAP 128 /* initial archive string table size */
-#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */
+#define _INIT_SYMOFF_CAP (256*(sizeof(uint64_t))) /* initial so table size */
#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */
#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */
#define _TRUNCATE_LEN 15 /* number of bytes to keep for member name */
@@ -557,6 +557,7 @@ write_cleanup(struct bsdar *bsdar)
free(bsdar->s_sn);
bsdar->as = NULL;
bsdar->s_so = NULL;
+ bsdar->s_so_max = 0;
bsdar->s_sn = NULL;
}
@@ -613,7 +614,10 @@ write_objs(struct bsdar *bsdar)
struct archive_entry *entry;
size_t s_sz; /* size of archive symbol table. */
size_t pm_sz; /* size of pseudo members */
- int i, nr;
+ size_t w_sz; /* size of words in symbol table */
+ uint64_t nr;
+ uint32_t nr32;
+ int i;
if (elf_version(EV_CURRENT) == EV_NONE)
bsdar_errc(bsdar, EX_SOFTWARE, 0,
@@ -628,9 +632,6 @@ write_objs(struct bsdar *bsdar)
if (strlen(obj->name) > _MAXNAMELEN_SVR4)
add_to_ar_str_table(bsdar, obj->name);
bsdar->rela_off += _ARHDR_LEN + obj->size + obj->size % 2;
- if (bsdar->rela_off > UINT32_MAX)
- bsdar_errc(bsdar, EX_SOFTWARE, 0,
- "Symbol table offset overflow");
}
/*
@@ -656,18 +657,31 @@ write_objs(struct bsdar *bsdar)
*
* absolute_offset = htobe32(relative_offset + size_of_pseudo_members)
*/
-
+ w_sz = sizeof(uint32_t);
if (bsdar->s_cnt != 0) {
s_sz = (bsdar->s_cnt + 1) * sizeof(uint32_t) + bsdar->s_sn_sz;
pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
if (bsdar->as != NULL)
pm_sz += _ARHDR_LEN + bsdar->as_sz;
- for (i = 0; (size_t)i < bsdar->s_cnt; i++) {
- if (*(bsdar->s_so + i) > UINT32_MAX - pm_sz)
- bsdar_errc(bsdar, EX_SOFTWARE, 0,
- "Symbol table offset overflow");
- *(bsdar->s_so + i) = htobe32(*(bsdar->s_so + i) +
- pm_sz);
+ /* Use the 64-bit word size format if necessary. */
+ if (bsdar->s_so_max > UINT32_MAX - pm_sz) {
+ w_sz = sizeof(uint64_t);
+ pm_sz -= s_sz;
+ s_sz = (bsdar->s_cnt + 1) * sizeof(uint64_t) +
+ bsdar->s_sn_sz;
+ pm_sz += s_sz;
+ /* Convert to big-endian. */
+ for (i = 0; (size_t)i < bsdar->s_cnt; i++)
+ bsdar->s_so[i] =
+ htobe64(bsdar->s_so[i] + pm_sz);
+ } else {
+ /*
+ * Convert to big-endian and shuffle in-place to
+ * the front of the allocation. XXX UB
+ */
+ for (i = 0; (size_t)i < bsdar->s_cnt; i++)
+ ((uint32_t *)(bsdar->s_so))[i] =
+ htobe32(bsdar->s_so[i] + pm_sz);
}
}
@@ -689,16 +703,23 @@ write_objs(struct bsdar *bsdar)
if (entry == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, 0,
"archive_entry_new failed");
- archive_entry_copy_pathname(entry, "/");
+ if (w_sz == sizeof(uint64_t))
+ archive_entry_copy_pathname(entry, "/SYM64/");
+ else
+ archive_entry_copy_pathname(entry, "/");
if ((bsdar->options & AR_D) == 0)
archive_entry_set_mtime(entry, time(NULL), 0);
- archive_entry_set_size(entry, (bsdar->s_cnt + 1) *
- sizeof(uint32_t) + bsdar->s_sn_sz);
+ archive_entry_set_size(entry, (bsdar->s_cnt + 1) * w_sz +
+ bsdar->s_sn_sz);
AC(archive_write_header(a, entry));
- nr = htobe32(bsdar->s_cnt);
- write_data(bsdar, a, &nr, sizeof(uint32_t));
- write_data(bsdar, a, bsdar->s_so, sizeof(uint32_t) *
- bsdar->s_cnt);
+ if (w_sz == sizeof(uint64_t)) {
+ nr = htobe64(bsdar->s_cnt);
+ write_data(bsdar, a, &nr, sizeof(nr));
+ } else {
+ nr32 = htobe32((uint32_t)bsdar->s_cnt);
+ write_data(bsdar, a, &nr32, sizeof(nr32));
+ }
+ write_data(bsdar, a, bsdar->s_so, w_sz * bsdar->s_cnt);
write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
archive_entry_free(entry);
}
@@ -904,13 +925,15 @@ add_to_ar_sym_table(struct bsdar *bsdar, const char *n
bsdar->s_sn_sz = 0;
}
- if (bsdar->s_cnt * sizeof(uint32_t) >= bsdar->s_so_cap) {
+ if (bsdar->s_cnt * sizeof(uint64_t) >= bsdar->s_so_cap) {
bsdar->s_so_cap *= 2;
bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
if (bsdar->s_so == NULL)
bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed");
}
bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
+ if ((uint64_t)bsdar->rela_off > bsdar->s_so_max)
+ bsdar->s_so_max = (uint64_t)bsdar->rela_off;
bsdar->s_cnt++;
/*
More information about the svn-src-stable
mailing list