
/*
 * reloc.c
 *
 * (C) Copyright 1995 Archie L. Cobbs
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "util.h"
#include "error.h"
#include "names.h"
#include "obj.h"
#include "load.h"

/*
 * DoRelocs()
 */

void
DoRelocs(FILE *fp, Byte *base, int num)
{
	int				k, bit, value;
	Byte			*address;
	struct ObjReloc	reloc;
	Symbol			sym;

	for (k = 0; k < num; k++)
	{
		if (fread(&reloc, sizeof(reloc), 1, fp) != 1)
		{
			if (ferror(fp))
				perror("reloc");
			cerror("can't read reloc");
		}

	/* Compute symbol's ultimate value */

		if (reloc.r_segrel)
			value = gBase[reloc.r_name];
		else if ((sym = GetSym(reloc.r_name)))
			value = gBase[sym->segment] + sym->offset;
		else
		{
			Unknown(reloc.r_name);
			continue;
		}

	/* Compute relocation locus and add offset to value */

		address = base + reloc.r_address;
		value += reloc.r_offset;

	/* Do the patch */

		if (reloc.r_bigend)
		{
			for (bit = 0x08; bit >= 1; bit >>= 1, value <<= 8)
				if (reloc.r_bytes & bit)
					*address++ = (Byte) (value >> 24);
		}
		else
			for (bit = 1; bit <= 0x08; bit <<= 1, value >>= 8)
				if (reloc.r_bytes & bit)
					*address++ = (Byte) value;
	}
}

