shithub: scc

Download patch

ref: 9f051be97f07bbb71ae4394a91f74ed5acbb007a
parent: 50ea4ac5339f17f0abf777d46b1719334e399173
author: Roberto E. Vargas Caballero <[email protected]>
date: Tue May 29 17:21:47 EDT 2018

[as/coff32] Calculate correct address for symbols

The address of every symbol depends of the relative address of
the section, and it means that we have to calculate the size
of the section before calculating the address of the symbol,
but we have to keep in mind tha the size was already increased.

--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -95,21 +95,30 @@
 	unsigned char buff[SCNHSZ];
 	SCNHDR *scn, *p;
 	FILHDR *hdr;
-	Symbol *sym;
+	Symbol *sym, **sec;
 
 	hdr = obj->filhdr;
 	nsec = hdr->f_nscns;
+
 	if (nsec > SIZE_MAX / sizeof(*scn))
 		return -1;
 
-	if ((scn = malloc(nsec * sizeof(*scn))) == NULL)
+	if (nsec > SIZE_MAX / sizeof(Symbol *))
 		return -1;
 
+	scn = malloc(nsec * sizeof(*scn));
+	sec = malloc(nsec * sizeof(Symbol *));
+	if (!scn || !sec)
+		outmem();
+	obj->sections = sec;
+	obj->scnhdr = scn;
+
 	if (fseek(obj->fp, off, SEEK_SET) == EOF)
 		return -1;
 
 	a = obj->align - 1;
-	for (p = scn; p < &scn[nsec]; ++p) {
+	for (i = 0; i < nsec; ++i) {
+		p = &scn[i];
 		if (fread(buff, SCNHSZ, 1, obj->fp) != 1)
 			return -1;
 		getscn(obj, buff, p);
@@ -123,8 +132,9 @@
 			exit(EXIT_FAILURE);
 		}
 		sym->size += p->s_size;
+		obj->sections[i] = sym;
+		
 	}
-	obj->scnhdr = scn;
 
 	return 0;
 }
@@ -216,7 +226,9 @@
 getval(Obj *obj, SYMENT *ent)
 {
 	FILHDR *hdr = obj->filhdr;;
-	SCNHDR *scn = obj->scnhdr;
+	SCNHDR *scn;
+	Symbol *sym;
+	unsigned n;
 
 	if (ent->n_scnum > hdr->f_nscns) {
 		fprintf(stderr,
@@ -226,13 +238,13 @@
 		exit(EXIT_FAILURE);
 	}
 
-	scn = &scn[ent->n_scnum-1];
+	n = ent->n_scnum-1;
+	scn = obj->scnhdr;
+	scn = &scn[n];
+	sym = obj->sections[n];
 
-	/*
-	 * TODO: We have to add the composed size of the segment minus
-	 * the size of the fragment
-	 */
-	return ent->n_value - scn->s_size;
+
+	return ent->n_value + (sym->size - scn->s_size);
 }
 
 static int
@@ -276,10 +288,13 @@
 		type = typeof(obj, &ent);
 		sym = lookup(name);
 
+		if (ent.n_scnum <= 0)
+			continue;
+
 		switch (sym->type) {
 		case 'U':
 			sym->type = type;
-			sym->value = ent.n_value;
+			sym->value = getval(obj, &ent);
 			if (type == 'C')
 				sym->size = ent.n_value;
 			break;
@@ -292,7 +307,7 @@
 				break;
 			default:
 				sym->type = type;
-				sym->value = ent.n_value;
+				sym->value = getval(obj, &ent);
 				break;
 			}
 			break;
@@ -328,7 +343,6 @@
 	getfhdr(obj, buff, hdr);
 	obj->filhdr = hdr;
 
-	/* TODO: Check overflow */
 	stroff = pos + hdr->f_symptr + hdr->f_nsyms*SYMESZ;
 	symoff = pos + hdr->f_symptr;
 	secoff = pos + FILHSZ + hdr->f_opthdr;
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -7,14 +7,20 @@
 	char *fname;
 	char *member;
 	FILE *fp;
+	Fmt *fmt;
+
 	void *filhdr;
 	void *scnhdr;
+
 	Symbol **symbols;
+	Symbol **sections;
+
 	char *strtbl;
 	size_t strsiz;
+
 	int (*unpack)(unsigned char *, char *, ...);
 	int align;
-	Fmt *fmt;
+
 	struct obj *next;
 };