/* Nuke the symbols _end, _etext, and _edata in an a.out file's symbol
 * table.  A bug in SGI's linker causes incremental loading of object
 * files to fail if the base a.out contains one of these linker-defined
 * symbols.
 */

#include <stdio.h>
#include <a.out.h>
#include <malloc.h>

char *badsyms[] = { "_end", "_etext", "_edata", 0 };

main(ac, av) char **av; {
    FILE *f;
    struct filehdr filehdr;
    HDRR symhdr;
    char **pp, *p, *strings;
    long max;
    int gotone = 0;

    if (ac != 2) {
	printf("Usage: %s a.out-file\n", ac == 0 ? "sgihack" : av[0]);
	return 1;
    }
    if ((f = fopen(av[1], "r+")) == 0) {
	printf("Cannot open %s\n", av[1]);
	return 1;
    }
    if (fread((char *)&filehdr, sizeof(filehdr), 1, f) != 1) {
	printf("Cannot read filehdr\n");
	return 1;
    }
    (void)fseek(f, filehdr.f_symptr, SEEK_SET);
    if (fread((char *)&symhdr, sizeof(symhdr), 1, f) != 1) {
	printf("Cannot read symhdr\n");
	return 1;
    }
    max = symhdr.issExtMax;
    if ((strings = malloc(max)) == 0) {
	printf("Cannot malloc %ld bytes\n", max);
	return 1;
    }
    (void)fseek(f, symhdr.cbSsExtOffset, SEEK_SET);
    if (fread(strings, 1, max, f) != max) {
	printf("Cannot read string table\n");
	return 1;
    }
    for (p = strings; p < strings+max; ) {
	for (pp = badsyms; *pp; pp++) {
	    if (strcmp(p, *pp) == 0) {
		gotone++;
		printf("Nuking symbol %s\n", p);
		p[0] = '?';
	    }
	}
	while (*p != '\0') p++;
	while (p < strings+max && *p == '\0') p++;
    }
    if (!gotone) {
	printf("No bad symbols found in %s\n", av[1]);
	return 0;
    }
    (void)fseek(f, symhdr.cbSsExtOffset, SEEK_SET);
    if (fwrite(strings, 1, max, f) != max) {
	printf("Cannot write back string table\n");
	return 1;
    }
    return 0;
}
