w6l: link GNU long-name archive members; bad members fail the link
The archive walk skipped every member whose header name starts with '/', which also dropped GNU long-name members (/N) -- any member with a >15-char filename silently never linked. Only '/ ' (symbol index) and '//' (long-name table) are non-objects; /N members index by content (names are never consulted). A member that fails loadimage in the selective pull also stayed silently unlinked with rc=0; it now reports and fails the link (rule 7). wwstage w6l diagnostics ride the same .len idiom as the w6a sweep.
This commit is contained in:
@@ -185,7 +185,16 @@ load_archive(Lnk *l, const char *path, u8 *buf, u64 len)
|
||||
u64 size = ar_field(hdr + 48, 10);
|
||||
u64 hdr_end = pos + 60;
|
||||
if (hdr_end + size > len) break;
|
||||
if (hdr[0] != '/' && hdr[0] != 0 && hdr[0] != ' ') {
|
||||
/* '/'-led names: '/ ' is the symbol index and '//' the GNU
|
||||
* long-name table — neither is an object. '/N' (digits) IS
|
||||
* a real member whose name lives in that table; names are
|
||||
* never consulted here, so index it by content. Pre-fix
|
||||
* every long-named (>15 char) member was silently skipped
|
||||
* and its definitions never linked. */
|
||||
int special = (hdr[0] == '/'
|
||||
&& (hdr[1] == ' ' || hdr[1] == '/'))
|
||||
|| hdr[0] == 0 || hdr[0] == ' ';
|
||||
if (!special) {
|
||||
ArMember *m = calloc(1, sizeof *m);
|
||||
m->size = size;
|
||||
m->data = malloc((size_t)size);
|
||||
@@ -213,6 +222,14 @@ load_archive(Lnk *l, const char *path, u8 *buf, u64 len)
|
||||
if (load_image(l, path, copy, m->size) == 0) {
|
||||
m->loaded = 1;
|
||||
changed = 1;
|
||||
} else {
|
||||
/* a member that fails to parse must fail
|
||||
* the link, not stay silently unlinked
|
||||
* (rule 7). Consumed either way. */
|
||||
fprintf(stderr,
|
||||
"w6l: %s: bad archive member\n", path);
|
||||
l->errs++;
|
||||
m->loaded = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user