scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 099548f9e14488bce21d9f894637e9a2905c3efe
parent a960beadc92a005fd0c0b38c70d95c6e5e8b2976
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 17 Jan 2025 17:38:28 +0100

libmach: Add support for long section names

This is a common extension and it makes sense to apply the
same hack that is done for ent and aux entries.

Diffstat:
Minclude/bits/scc/coff32/scnhdr.h | 12+++++++++++-
Msrc/libmach/coff32/coff32getsec.c | 11++++++++++-
Msrc/libmach/coff32/coff32read.c | 5+++++
Msrc/libmach/coff32/coff32setsec.c | 27++++++++++++++++++++++++++-
Msrc/libmach/coff32/coff32write.c | 64++++++++++++++++++++++++++++++++++++----------------------------
5 files changed, 88 insertions(+), 31 deletions(-)

diff --git a/include/bits/scc/coff32/scnhdr.h b/include/bits/scc/coff32/scnhdr.h @@ -2,8 +2,18 @@ #define SCNNMLEN 8 +#define s_name _s._s_name +#define s_zeroes _s._s_s._s_zeroes +#define s_offset _s._s_s._s_offset + struct scnhdr { - char s_name[SCNNMLEN]; /* section name */ + union { + char _s_name[SCNNMLEN]; /* section name */ + struct { + long _s_zeroes; /* if _s_name[0-3] == 0 */ + long _s_offset; /* offset into string table */ + } _s_s; + } _s; long s_paddr; /* physical address */ long s_vaddr; /* virtual address */ long s_size; /* section size */ diff --git a/src/libmach/coff32/coff32getsec.c b/src/libmach/coff32/coff32getsec.c @@ -5,6 +5,15 @@ #include "../libmach.h" #include "coff32.h" +static char * +secname(Coff32 *coff, SCNHDR *scn) +{ + if (scn->s_zeroes != 0) + return scn->s_name; + + return &coff->strtbl[scn->s_offset]; +} + Section * coff32getsec(Obj *obj, int *idx, Section *sec) { @@ -79,7 +88,7 @@ coff32getsec(Obj *obj, int *idx, Section *sec) break; } - sec->name = scn->s_name; + sec->name = secname(coff, scn); sec->index = n; sec->size = scn->s_size; sec->base = scn->s_vaddr; diff --git a/src/libmach/coff32/coff32read.c b/src/libmach/coff32/coff32read.c @@ -46,6 +46,7 @@ static void unpack_scn(int order, unsigned char *buf, SCNHDR *scn) { int n; + char *s; n = unpack(order, buf, @@ -61,6 +62,10 @@ unpack_scn(int order, unsigned char *buf, SCNHDR *scn) &scn->s_nlnno, &scn->s_flags); assert(n == SCNHSZ); + + s = scn->s_name; + if (!s[0] && !s[1] && !s[2] && !s[3]) + unpack(order, buf, "ll", &scn->s_zeroes, &scn->s_offset); } static void diff --git a/src/libmach/coff32/coff32setsec.c b/src/libmach/coff32/coff32setsec.c @@ -8,6 +8,29 @@ #include "../libmach.h" #include "coff32.h" +static char * +secname(Coff32 *coff, SCNHDR *scn, Section *sec) +{ + char *p; + unsigned long siz = strlen(sec->name); + + if (siz < SCNNMLEN) + return strncpy(scn->s_name, sec->name, SCNNMLEN); + + if (coff->strsiz > ULONG_MAX - siz - 1) + return NULL; + + siz += coff->strsiz + 1; + if ((p = realloc(coff->strtbl, siz)) == NULL) + return NULL; + coff->strtbl = p; + + scn->s_zeroes = 0; + scn->s_offset = coff->strsiz; + coff->strsiz += siz; + return strcpy(&coff->strtbl[scn->s_offset], sec->name); +} + Section * coff32setsec(Obj *obj, int *idx, Section *sec) { @@ -65,9 +88,11 @@ coff32setsec(Obj *obj, int *idx, Section *sec) coff->scns = scn; hdr->f_nscns = n + 1; } + scn = &coff->scns[n]; + if (!secname(coff, scn, sec)) + return NULL; - strncpy(scn->s_name, sec->name, SCNNMLEN); scn->s_paddr = 0; scn->s_vaddr = sec->base; scn->s_size = sec->size; diff --git a/src/libmach/coff32/coff32write.c b/src/libmach/coff32/coff32write.c @@ -38,10 +38,14 @@ pack_scn(int order, unsigned char *buf, SCNHDR *scn) { int n; + if (scn->s_zeroes == 0) + pack(order, buf, "ll", scn->s_zeroes, scn->s_offset); + else + memcpy(buf, scn->s_name, 8); + n = pack(order, - buf, - "'8llllllssl", - scn->s_name, + buf + 8, + "llllllssl", scn->s_paddr, scn->s_vaddr, scn->s_size, @@ -51,6 +55,7 @@ pack_scn(int order, unsigned char *buf, SCNHDR *scn) scn->s_nrelloc, scn->s_nlnno, scn->s_flags); + n += 8; assert(n == SCNHSZ); } @@ -58,7 +63,6 @@ static void pack_ent(int order, unsigned char *buf, SYMENT *ent) { int n; - char *s; if (ent->n_zeroes == 0) pack(order, buf, "ll", ent->n_zeroes, ent->n_offset); @@ -66,7 +70,7 @@ pack_ent(int order, unsigned char *buf, SYMENT *ent) memcpy(buf, ent->n_name, 8); n = pack(order, - buf, + buf + 8, "lsscc", ent->n_value, ent->n_scnum, @@ -224,28 +228,6 @@ writehdr(Obj *obj, FILE *fp) } static int -writescns(Obj *obj, FILE *fp) -{ - int i; - SCNHDR *scn; - FILHDR *hdr; - struct coff32 *coff; - unsigned char buf[SCNHSZ]; - - coff = obj->data; - hdr = &coff->hdr; - - for (i = 0; i < hdr->f_nscns; i++) { - scn = &coff->scns[i]; - pack_scn(ORDER(obj->type), buf, scn); - if (fwrite(buf, SCNHSZ, 1, fp) != 1) - return 0; - } - - return 1; -} - -static int allocstring(struct coff32 *coff, long off, struct strtbl *tbl) { char *s, *name; @@ -269,6 +251,32 @@ allocstring(struct coff32 *coff, long off, struct strtbl *tbl) } static int +writescns(Obj *obj, FILE *fp, struct strtbl *tbl) +{ + int i; + SCNHDR *scn; + FILHDR *hdr; + struct coff32 *coff; + unsigned char buf[SCNHSZ]; + + coff = obj->data; + hdr = &coff->hdr; + + for (i = 0; i < hdr->f_nscns; i++) { + scn = &coff->scns[i]; + if (scn->s_zeroes == 0) { + if (!allocstring(coff, scn->s_offset, tbl)) + return 0; + } + pack_scn(ORDER(obj->type), buf, scn); + if (fwrite(buf, SCNHSZ, 1, fp) != 1) + return 0; + } + + return 1; +} + +static int writeents(Obj *obj, FILE *fp, struct strtbl *tbl) { long i; @@ -510,7 +518,7 @@ coff32write(Obj *obj, Map *map, FILE *fp) goto err; if (!writeaout(obj, fp)) goto err; - if (!writescns(obj, fp)) + if (!writescns(obj, fp, &tbl)) goto err; if (!writedata(obj, map, fp)) goto err;