view src/link.c @ 301:376cc55361c7

section order and address resolution done
author lost
date Wed, 21 Jan 2009 05:45:25 +0000
parents
children eff969272fb9
line wrap: on
line source

/*
link.c
Copyright © 2009 William Astle

This file is part of LWLINK.

LWLINK is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.


Resolve section and symbol addresses; handle incomplete references
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>

#include "lwlink.h"
#include "util.h"

struct section_list
{
	section_t *ptr;		// ptr to section structure
	int forceaddr;		// was this force to an address by the link script?
};

static struct section_list *sectlist = NULL;
static int nsects = 0;

// work out section load order and resolve base addresses for each section
// make a list of sections to load in order
void resolve_sections(void)
{
	int laddr = 0;
	int ln, sn, fn;
	
	for (ln = 0; ln < linkscript.nlines; ln++)
	{
		if (linkscript.lines[ln].sectname)
		{
			int f = 0;
			// named section
			// look for all instances of a section by the specified name
			// and resolve base addresses and add to the list
			for (fn = 0; fn < ninputfiles; fn++)
			{
				for (sn = 0; sn < inputfiles[fn] -> nsections; sn++)
				{
					if (!strcmp(linkscript.lines[ln].sectname, inputfiles[fn] -> sections[sn].name))
					{
						// we have a match
						sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1));
						sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]);
						
						inputfiles[fn] -> sections[sn].processed = 1;
						if (!f && linkscript.lines[ln].loadat >= 0)
						{
							f = 1;
							sectlist[nsects].forceaddr = 1;
							laddr = linkscript.lines[ln].loadat;
						}
						else
						{
							sectlist[nsects].forceaddr = 0;
						}
						inputfiles[fn] -> sections[sn].loadaddress = laddr;
						nsects++;
					}
				}
			}
		}
		else
		{
			// wildcard section
			// look for all sections not yet processed that match flags

			int f = 0;
			int fn0, sn0;
			char *sname;
			
			// named section
			// look for all instances of a section by the specified name
			// and resolve base addresses and add to the list
			for (fn0 = 0; fn0 < ninputfiles; fn0++)
			{
				for (sn0 = 0; sn0 < inputfiles[fn0] -> nsections; sn0++)
				{
					// ignore if the "no flags" bit says to
					if (linkscript.lines[ln].noflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].noflags))
						continue;
					// ignore unless the yes flags tell us not to
					if (linkscript.lines[ln].yesflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].yesflags == 0))
						continue;
					if (inputfiles[fn0] -> sections[sn0].processed == 0)
					{
						sname = inputfiles[fn0] -> sections[sn0].name;
						for (fn = 0; fn < ninputfiles; fn++)
						{
							for (sn = 0; sn < inputfiles[fn] -> nsections; sn++)
							{
								if (!strcmp(sname, inputfiles[fn] -> sections[sn].name))
								{
									// we have a match
									sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1));
									sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]);
						
									inputfiles[fn] -> sections[sn].processed = 1;
									if (!f && linkscript.lines[ln].loadat >= 0)
									{
										f = 1;
										sectlist[nsects].forceaddr = 1;
										laddr = linkscript.lines[ln].loadat;
									}
									else
									{
										sectlist[nsects].forceaddr = 0;
									}
									inputfiles[fn] -> sections[sn].loadaddress = laddr;
									nsects++;
								}
							}
						}
					}
				}
			}
		}
	}
	
	// theoretically, all the base addresses are set now
}