1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441 |
- /* special.c: Routines to handle special characteristics of the linker
- Copyright (C) 2002-2004 Sebastian Reichelt
- Copyright (C) 2003-2008 Kevin Kofler
- Copyright (C) 2004 Billy Charvet
- Copyright (C) 2008 Lionel Debroux
- This program 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 2, 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, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- #include "special.h"
- #include "integers.h"
- #include "manip.h"
- #include "insert/insert.h"
- #include <string.h>
- #include <stdlib.h>
- // Try to translate an external symbol into a special-feature symbol used by the linker.
- // If the symbol contains a number, it is written to the variable pointed to by Number.
- SpecialExternalSymbolTypes TranslateSpecialExternalSymbol (PROGRAM *Program, char *SymbolName, void **Reference, OFFSET *Number)
- {
- SpecialExternalSymbolTypes SymType = ST_NORMAL;
- char *SymNum = SymbolName, *Divider = NULL;
- int NumBase = 16;
-
- if (!(strncmp (SymbolName, "tiamsapi_", sizeof ("tiamsapi_") - 1)))
- {
- SymType = ST_ROM_CALL;
- SymNum += sizeof ("tiamsapi_") - 1;
- NumBase = 10;
- }
- if (!(strncmp (SymbolName, "_ROM_CALL_", sizeof ("_ROM_CALL_") - 1)))
- {
- SymType = ST_ROM_CALL;
- SymNum += sizeof ("_ROM_CALL_") - 1;
- }
- else if (!(strncmp (SymbolName, "_RAM_CALL_", sizeof ("_RAM_CALL_") - 1)))
- {
- SymType = ST_RAM_CALL;
- SymNum += sizeof ("_RAM_CALL_") - 1;
- }
- else if (!(strncmp (SymbolName, "_extraramaddr@", sizeof ("_extraramaddr@") - 1)))
- {
- SymType = ST_EXTRA_RAM;
- SymNum += sizeof ("_extraramaddr@") - 1;
- }
- else if (!(strncmp (SymbolName, "_extraramaddr__", sizeof ("_extraramaddr__") - 1)))
- {
- SymType = ST_EXTRA_RAM;
- SymNum += sizeof ("_extraramaddr__") - 1;
- }
- else if (((Divider = strchr (SymbolName, '@'))) || (((Divider = strstr (SymbolName, "__"))) && (SymbolName [0] != '_') && (SymbolName [0] != '.') && (strncmp (SymbolName, "L_", sizeof ("L_") - 1))))
- {
- if (*Divider == '@')
- SymNum = Divider + 1;
- else
- SymNum = Divider + 2;
- if (strlen (SymNum) == 4)
- SymType = ST_LIB_CALL;
- }
-
- if (SymType != ST_NORMAL)
- {
- // Get the number the symbol contains (in hex).
- if (Number)
- {
- char *Err;
- *Number = strtoul (SymNum, &Err, NumBase);
- // If the number has an error in it, revert to normal symbol.
- if (*Err)
- SymType = ST_NORMAL;
- }
- }
-
- if (SymType == ST_LIB_CALL)
- {
- // Cut SymbolName at the divider.
- *Divider = 0;
- // Get a reference to the library identified by SymbolName.
- if (Reference)
- {
- *Reference = GetLibrary (Program, SymbolName);
- if (!(*Reference))
- SymType = ST_NORMAL;
- }
- }
-
- return SymType;
- }
- // Handle the symbol if it is a special one.
- // Returns TRUE if it was special; in this case it should not be used.
- BOOLEAN HandleSpecialSymbol (PROGRAM *Program, const char *SymbolName)
- {
- BOOLEAN SymbolNameMatches (const char *Name)
- {
- return (!(strcmp (SymbolName, Name)));
- }
-
- const char *Divider;
-
- // All special symbols start with an underscore.
- if (SymbolName [0] == '_')
- {
- SymbolName++;
-
- // The most important special symbol: __ref_all_xxx.
- // It adds xxx to the global imports.
- if (!(strncmp (SymbolName, "_ref_all_", sizeof ("_ref_all_") - 1)))
- {
- if (!(Program->IgnoreGlobalImports))
- AddGlobalImport (Program, SymbolName + sizeof ("_ref_all_") - 1);
- }
- else if (SymbolNameMatches ("tigcc_native"))
- {
- // Kernel is the default type. Everything else must be defined explicitly
- // and should therefore take precedence over _tigcc_native.
- if (Program->Type == PT_KERNEL)
- Program->Type = PT_NATIVE;
- }
- else if (SymbolNameMatches ("nostub"))
- {
- SECTION *FirstSection = GetFirst (Program->Sections);
- if (FirstSection && (!(FirstSection->StartupNumber)))
- FirstSection->Essential = TRUE;
- Program->Type = PT_NOSTUB;
- }
- #ifdef NOSTUB_DLL_SUPPORT
- else if (SymbolNameMatches ("nostub_dll"))
- {
- SECTION *FirstSection = GetFirst (Program->Sections);
- if (FirstSection && (!(FirstSection->StartupNumber)))
- FirstSection->Essential = TRUE;
- Program->Type = PT_NOSTUB_DLL;
- Program->Library = TRUE;
- }
- #endif /* NOSTUB_DLL_SUPPORT */
- #ifdef FARGO_SUPPORT
- else if (SymbolNameMatches ("fargo"))
- Program->Type = PT_FARGO;
- #endif /* FARGO_SUPPORT */
- #ifdef FLASH_OS_SUPPORT
- else if (SymbolNameMatches ("flash_os"))
- Program->Type = PT_FLASH_OS;
- #endif /* FLASH_OS_SUPPORT */
- else if (SymbolNameMatches ("library"))
- {
- Program->Library = TRUE;
- #ifdef FARGO_SUPPORT
- // Under Fargo, _library is a normal symbol as well.
- if (Program->Type == PT_FARGO)
- return FALSE;
- #endif /* FARGO_SUPPORT */
- }
- else if (SymbolNameMatches ("ti92"))
- {
- Program->Calcs |= CALC_TI92;
- }
- else if (SymbolNameMatches ("ti89"))
- {
- Program->Calcs |= CALC_TI89;
- Program->KernelFlags |= 0x02;
- }
- else if (SymbolNameMatches ("ti89ti"))
- {
- Program->Calcs |= CALC_TI89 | CALC_FLAG_TITANIUM;
- Program->KernelFlags |= 0x42;
- }
- else if (SymbolNameMatches ("ti92plus"))
- {
- Program->Calcs |= CALC_TI92PLUS;
- Program->KernelFlags |= 0x01;
- }
- else if (SymbolNameMatches ("v200"))
- {
- Program->Calcs |= CALC_V200;
- Program->KernelFlags |= 0x20;
- }
- else if (!(strncmp (SymbolName, "flag_", sizeof ("flag_") - 1)))
- Program->KernelFlags |= (1 << strtoul (SymbolName + sizeof ("flag_") - 1, NULL, 10));
- else if (!(strncmp (SymbolName, "version", sizeof ("version") - 1)))
- Program->Version = strtoul (SymbolName + sizeof ("version") - 1, NULL, 16);
- else if (!(strcmp (SymbolName, "_ld_use_fline_jumps")))
- {
- if (Program->OptimizeInfo)
- Program->OptimizeInfo->UseFLineJumps = TRUE;
- }
- else if (!(strcmp (SymbolName, "_ld_use_4byte_fline_jumps")))
- {
- if (Program->OptimizeInfo)
- Program->OptimizeInfo->Use4ByteFLineJumps = TRUE;
- }
- else if (!(strcmp (SymbolName, SYM_IGNORE_GLOBAL_IMPORTS + 1)))
- Program->IgnoreGlobalImports = TRUE;
- else if (SymbolNameMatches (SYM_OMIT_BSS_INIT + 1) || SymbolNameMatches (SYM_ALL_RELOCS + 1))
- // These are mostly file-local special symbols; they are handled
- // by the importing function.
- ;
- else
- // Not a special symbol.
- return FALSE;
-
- // The symbol was handled here.
- return TRUE;
- }
- else if (((Divider = strstr (SymbolName, "@version"))) || (((Divider = strstr (SymbolName, "__version"))) && (SymbolName [0] != '_') && (SymbolName [0] != '.') && (strncmp (SymbolName, "L_", sizeof ("L_") - 1))))
- {
- // Required minimum version number for a library.
- const char *Version;
- VERSION VersionNumber;
-
- if (*Divider == '@')
- Version = Divider + sizeof ("@version") - 1;
- else
- Version = Divider + sizeof ("__version") - 1;
- VersionNumber = strtoul (Version, NULL, 16);
-
- if (VersionNumber)
- {
- if (Divider - SymbolName <= MAX_SYM_LEN)
- {
- char LibName[MAX_SYM_LEN+1];
- LIBRARY *Library;
-
- strncpy (LibName, SymbolName, Divider - SymbolName);
- LibName [Divider - SymbolName] = 0;
- Library = GetLibrary (Program, LibName);
- if (Library && (Library->Version < VersionNumber))
- Library->Version = VersionNumber;
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
- }
- // Translate a section name into a startup section number.
- // Returns 0 if the name does not represent a startup section.
- OFFSET GetStartupSectionNumber (const char *SectionName, SIZE MaxLen)
- {
- // Check if it looks like a startup section.
- if ((MaxLen > (SIZE) (sizeof ("_st") - 1)) && (!(strncmp (SectionName, "_st", sizeof ("_st") - 1))))
- {
- // Copy the section name to a temporary null-terminated location.
- char SecName[MaxLen+1];
- memset (SecName, 0, MaxLen + 1);
- strncpy (SecName, SectionName, MaxLen);
- // Check whether it is a library startup section.
- if (SecName [sizeof ("_st") - 1] == 'l')
- {
- // Library startup sections are special:
- // They may always be included, even if the file is not executable.
- // Therefore they get a negative number to distinguish them.
- OFFSET RealNum = strtoul (SecName + sizeof ("_stl") - 1, NULL, 10);
- return (RealNum ? RealNum - 10000 : 0);
- }
- else
- return (strtoul (SecName + sizeof ("_st") - 1, NULL, 10));
- }
- else
- return 0;
- }
- // Translate a symbol name into the number of an exported function, if the
- // function is meant to be exported.
- // Returns -1 if it is not an exported function.
- OFFSET GetExportNumber (const char *SymbolName)
- {
- const char *Divider;
-
- if (((Divider = strchr (SymbolName, '@'))) || (((Divider = strstr (SymbolName, "__"))) && (SymbolName [0] != '_') && (SymbolName [0] != '.') && (strncmp (SymbolName, "L_", sizeof ("L_") - 1))))
- {
- OFFSET Number;
- char *Err;
-
- if (*Divider == '@')
- Divider++;
- else
- Divider += 2;
-
- Number = strtoul (Divider, &Err, 16);
- if (*Err)
- return (-1);
-
- return Number;
- }
- else
- return (-1);
- }
- // Add all imports with names defined by this program, if they are needed.
- BOOLEAN CreateSpecialGlobalImports (PROGRAM *Program)
- {
- BOOLEAN Result = TRUE;
- SECTION *TempSection;
-
- if (Program->Type == PT_KERNEL)
- {
- if (Program->Library)
- Result = Result && AddGlobalImport (Program, "__kernel_library_header");
- else
- Result = Result && AddGlobalImport (Program, "__kernel_program_header");
- }
- #ifdef FARGO_SUPPORT
- else if (Program->Type == PT_FARGO)
- {
- if (Program->Library)
- Result = Result && AddGlobalImport (Program, "__fargo_library_header");
- else
- Result = Result && AddGlobalImport (Program, "__fargo_program_header");
- }
- #endif /* FARGO_SUPPORT */
- #ifdef FLASH_OS_SUPPORT
- else if (Program->Type == PT_FLASH_OS)
- Result = Result && AddGlobalImport (Program, "__flash_os_header");
- #endif /* FLASH_OS_SUPPORT */
- if (Program->Constructors.Start)
- Result = Result && AddGlobalImport (Program, "__handle_constructors");
- if (Program->Destructors.Start)
- Result = Result && AddGlobalImport (Program, "__handle_destructors");
- if (Program->BSSSection && Program->BSSSection->Initialized
- #ifdef FLASH_OS_SUPPORT
- && Program->Type != PT_FLASH_OS
- #endif /* FLASH_OS_SUPPORT */
- ) Result = Result && AddGlobalImport (Program, "__initialize_bss");
-
- // Handle BSS section if any.
- if (Program->BSSSection && (!(Program->BSSSection->Handled)))
- {
- GLOBAL_IMPORT *Import = CreateGlobalImport (Program, "__handle_bss");
- if (Import)
- {
- // This is the import that will mark the BSS section as handled
- // if it succeeds.
- Program->BSSImport = Import;
-
- // Try to resolve it against available archives.
- ResolveGlobalImport (Program, Import);
-
- // The BSS section is simply merged into the rest if it is not
- // handled.
- Import->Succeeded = TRUE;
- }
- else
- Result = FALSE;
- }
-
- // Handle absolute relocs if there are any.
- for_each (TempSection, Program->Sections)
- {
- BOOLEAN Done = FALSE;
- RELOC *TempReloc;
- for_each (TempReloc, TempSection->Relocs)
- {
- if ((!(TempReloc->Relative || TempReloc->Target.Builtin || (TempReloc->Target.Symbol && (TempReloc->Target.Symbol->Parent->Handled)))))
- {
- GLOBAL_IMPORT *Import = AddGlobalImport (Program, "__handle_relocs");
- if (Import)
- // Relocs are either handled by the export format, or a
- // warning is emitted.
- Import->Succeeded = TRUE;
- else
- Result = FALSE;
- Done = TRUE;
- break;
- }
- }
- if (Done)
- break;
- }
-
- // Handle ROM calls if there are any.
- for_each (TempSection, Program->Sections)
- {
- if (!(IsEmpty (TempSection->ROMCalls)))
- {
- GLOBAL_IMPORT *Import = AddGlobalImport (Program, "__handle_rom_calls");
- if (Import)
- // ROM calls are either handled by the export format, or a
- // warning is emitted.
- Import->Succeeded = TRUE;
- else
- Result = FALSE;
- break;
- }
- }
-
- // Handle RAM calls if there are any.
- for_each (TempSection, Program->Sections)
- {
- if (!(IsEmpty (TempSection->RAMCalls)))
- {
- GLOBAL_IMPORT *Import = AddGlobalImport (Program, "__handle_ram_calls");
- if (Import)
- // RAM calls are either handled by the export format, or a
- // warning is emitted.
- Import->Succeeded = TRUE;
- else
- Result = FALSE;
- break;
- }
- }
-
- // Handle libraries if any libraries are referenced.
- if (!(IsEmpty (Program->Libraries)))
- {
- GLOBAL_IMPORT *Import = AddGlobalImport (Program, "__handle_libraries");
- if (Import)
- // Libraries are either handled by the export format, or a
- // warning is emitted.
- Import->Succeeded = TRUE;
- else
- Result = FALSE;
- }
-
- // Handle _nostub comments if any.
- if ((Program->Type == PT_NATIVE) || (Program->Type == PT_NOSTUB))
- {
- BOOLEAN NostubComments = FALSE;
- for_each (TempSection, Program->Sections)
- {
- SYMBOL *TempSymbol;
- for_each (TempSymbol, TempSection->Symbols)
- {
- if (TempSymbol->Exported && (!(strncmp (TempSymbol->Name, "_nostub_data__", sizeof ("_nostub_data__") - 1))))
- {
- OFFSET ExportNumber = GetExportNumber (TempSymbol->Name + sizeof ("_nostub_") - 1);
- if (ExportNumber >= 0)
- {
- NostubComments = TRUE;
- TempSection->Essential = TRUE;
- break;
- }
- }
- }
- }
- if (NostubComments)
- Result = Result && AddGlobalImport (Program, "__nostub_comment_header");
- }
-
- #ifdef DATA_VAR_SUPPORT
- // Handle data variable if desired.
- if (Program->DataVarInfo->Name && Program->DataSection)
- {
- Result = Result && (AddGlobalImport (Program, "__handle_data_var"));
- if (Program->DataVarInfo->CreateCopy)
- {
- Result = Result && (AddGlobalImport (Program, "__data_var_create_copy"));
- if (Program->DataVarInfo->CopyOnlyIfArchived)
- Result = Result && (AddGlobalImport (Program, "__data_var_copy_if_archived"));
- }
- }
- #endif /* DATA_VAR_SUPPORT */
-
- return Result;
- }
- // If the reloc or its relation point to a special ld-exported symbol,
- // change it to the appropriate value if possible. FALSE is returned
- // only if it is not a special symbol location, or if there was an error.
- BOOLEAN ResolveSpecialSymbolReloc (RELOC *Reloc, BOOLEAN *TryAgain)
- {
- // At first, resolve the relation, because if this is a built-in
- // number, we cannot write it into the section contents directly,
- // but we have to subtract it from FixedOffset.
- BOOLEAN Result = ResolveSpecialSymbolRelocRelation (Reloc, TryAgain);
-
- // Now resolve the target.
- return (ResolveSpecialSymbolRelocTarget (Reloc, TryAgain) ? Result : FALSE);
- }
-
- // If the reloc points to a special ld-exported symbol, change it to the
- // appropriate value if possible. FALSE is returned only if it is not a
- // special symbol reloc, or if there was an error.
- BOOLEAN ResolveSpecialSymbolRelocTarget (RELOC *Reloc, BOOLEAN *TryAgain)
- {
- BOOLEAN Result = FALSE;
- SECTION *Section = Reloc->Parent;
- LOCATION *Location = &(Reloc->Target);
-
- // If the relation is an unresolved reference to a builtin number,
- // do not even try to resolve the target. This would only cause
- // trouble, since we would need to handle it immediately if it
- // resolved to a number. There will be another call to this anyway
- // after the relation has finally been resolved.
- // Usually, we would at least need to set the Target.Builtin flag.
- // However, currently all tests which check for Target.Builtin also
- // check for Relation or Relative in general. If this ever changes,
- // this code will break.
- if (Reloc->Relation && Reloc->Relation->Builtin)
- return TRUE;
-
- if (ResolveSpecialSymbolLocation (Section, Location, TryAgain))
- {
- // If it has resolved to a number, write it into the section
- // contents.
- if (!(Location->Symbol || Location->SymbolName))
- {
- if (Reloc->Relation)
- Warning (GetFileName (Section, Reloc->Location), "Ignoring invalid negative reference to `%s' at 0x%lX.", Reloc->Relation->SymbolName, (long) Reloc->Location);
-
- if ((Reloc->Location >= 0) && (Reloc->Location + Reloc->Size <= Section->Size))
- {
- // Add the target offset (to support things such as "__ld_xxx+1").
- OFFSET NewValue = Location->Offset + Reloc->FixedOffset;
-
- if (Reloc->Relative)
- Warning (GetFileName (Section, Reloc->Location), "Invalid relative reference to built-in number `%s' at 0x%lX; changing to absolute.", Reloc->Target.SymbolName, (long) Reloc->Location);
-
- // Check if the section contents at the reloc are zero.
- if (!(IsZeroDataRange (Section, Reloc->Location, Reloc->Location + Reloc->Size)))
- Warning (GetFileName (Section, Reloc->Location), "Builtin reloc at 0x%lX to `%s' on nonzero section contents. Overlapping with another?", (long) Reloc->Location, Reloc->Target.SymbolName);
-
- // Resolve the reloc by writing the value into the section.
- Result = AddTI (Section->Data + Reloc->Location, Reloc->Size, NewValue, TRUE, TRUE);
-
- if (!Result)
- Error (GetFileName (Section, Reloc->Location), "Number `%s' (=%ld) too large for size %ld reloc at 0x%lX.", Reloc->Target.SymbolName, (long) NewValue, (long) Reloc->Size, (long) Reloc->Location);
- }
- else
- {
- Warning (GetFileName (Section, Reloc->Location), "Removing reloc at 0x%lX to `%s' outside of section.", (long) Reloc->Location, Reloc->Target.SymbolName);
- Result = TRUE;
- }
-
- FreeReloc (Reloc);
- }
- else
- Result = TRUE;
- }
-
- return Result;
- }
- // If the reloc's relation points to a special ld-exported symbol,
- // change it to the appropriate value if possible. FALSE is returned
- // only if it is not a special symbol location, or if there was an error.
- BOOLEAN ResolveSpecialSymbolRelocRelation (RELOC *Reloc, BOOLEAN *TryAgain)
- {
- BOOLEAN Result = FALSE;
- SECTION *Section = Reloc->Parent;
- LOCATION *Location = Reloc->Relation;
-
- if (Reloc->Relation)
- {
- // Try to resolve the relation.
- if (ResolveSpecialSymbolLocation (Section, Location, TryAgain))
- {
- // Check if it has really been resolved.
- BOOLEAN Resolved = (Location->Symbol != NULL);
-
- // If it has been resolved to a number, subtract it from
- // FixedOffset.
- if (!(Location->Symbol || Location->SymbolName))
- {
- Reloc->FixedOffset -= Location->Offset;
- FreeRelocRelation (Reloc);
- Resolved = TRUE;
- }
-
- Result = TRUE;
- }
- }
-
- return Result;
- }
- // If the location points to a special ld-exported symbol, change it to the
- // appropriate value if possible. FALSE is returned only if it is not a
- // special symbol location, or if there was an error.
- // Warning: If the special symbol resolves to a number, Location->Symbol and
- // Location->SymbolName will both be NULL, and Location->Offset will contain
- // the number.
- BOOLEAN ResolveSpecialSymbolLocation (SECTION *Section, LOCATION *Location, BOOLEAN *TryAgain)
- {
- const char *SymName = Location->SymbolName;
-
- BOOLEAN SymNameMatches (const char *Name)
- {
- return (!(strcmp (SymName, Name)));
- }
-
- // Locations that are already resolved do not need any treatment.
- if (Location->Symbol)
- return FALSE;
-
- // All special symbols start with '_'.
- if (SymName && (SymName [0] == '_'))
- {
- PROGRAM *Program = Section->Parent;
- BOOLEAN SetToEntryPoint = FALSE;
- OFFSET NewValue = 0;
-
- SymName++;
-
- // All built-in symbols start with "__ld_".
- if (!(strncmp (SymName, SYMPF_BUILTIN + 1, sizeof (SYMPF_BUILTIN) - 2)))
- {
- SIZE SymNameLength;
- BOOLEAN HasValue = FALSE;
- SYMBOL *NewSymbol = NULL;
- OFFSET NewTargetOffset = 0;
- SECTION *TempSection;
-
- // Skip the "__ld_" prefix.
- SymName += sizeof (SYMPF_BUILTIN) - 2;
- SymNameLength = strlen (SymName);
-
- // Find (but do not resolve) calculator constants.
- if (IsCalcBuiltinLocation (Location))
- ;
- // Resolve references to insertions.
- else if (!(strncmp (SymName, SYMPF_INSERT, sizeof (SYMPF_INSERT) - 1)))
- {
- if ((!(TempSection = Program->MainSection))
- || (!(NewSymbol = HandleAutoInsertion (TempSection, Location->SymbolName))))
- return TRUE;
- }
- // Resolve "has_...s".
- else if ((!(strncmp (SymName, "has_", sizeof ("has_") - 1))) && (SymName [SymNameLength - 1] == 's'))
- {
- if (Program->ResolveAllBuiltins)
- {
- Program->Frozen = TRUE;
- if (GetBuiltinValue (Program, SymName + (sizeof ("has_") - 1), SymNameLength - 1 - (sizeof ("has_") - 1), &NewValue, -1))
- HasValue = TRUE;
- }
- }
- // Resolve "..._count".
- else if ((SymNameLength > ((SIZE) (sizeof ("_count") - 1))) && (!(strcmp (SymName + SymNameLength - (sizeof ("_count") - 1), "_count"))))
- {
- if (Program->ResolveAllBuiltins)
- {
- Program->Frozen = TRUE;
- if (GetBuiltinValue (Program, SymName, SymNameLength - (sizeof ("_count") - 1), &NewValue, 0))
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("entry_point"))
- SetToEntryPoint = TRUE;
- else if (SymNameMatches ("entry_point_plus_0x8000"))
- {
- SetToEntryPoint = TRUE;
- NewValue = 0x8000;
- }
- else if (SymNameMatches ("constructors_start"))
- {
- if (!(NewSymbol = Program->Constructors.Start))
- return TRUE;
- }
- else if (SymNameMatches ("constructors_end"))
- {
- if (!(NewSymbol = Program->Constructors.End))
- return TRUE;
- }
- else if (SymNameMatches ("constructors_size"))
- {
- if (Program->Constructors.Start && Program->Constructors.End)
- {
- NewValue = Program->Constructors.End->Location - Program->Constructors.Start->Location;
- HasValue = TRUE;
- }
- else if (Program->ResolveAllBuiltins)
- HasValue = TRUE;
- }
- else if (SymNameMatches ("destructors_start"))
- {
- if (!(NewSymbol = Program->Destructors.Start))
- return TRUE;
- }
- else if (SymNameMatches ("destructors_end"))
- {
- if (!(NewSymbol = Program->Destructors.End))
- return TRUE;
- }
- else if (SymNameMatches ("destructors_size"))
- {
- if (Program->Destructors.Start && Program->Destructors.End)
- {
- NewValue = Program->Destructors.End->Location - Program->Destructors.Start->Location;
- HasValue = TRUE;
- }
- else if (Program->ResolveAllBuiltins)
- HasValue = TRUE;
- }
- else if (SymNameMatches ("data_start"))
- {
- if (Program->DataSection)
- NewSymbol = Program->DataSection->SectionSymbol;
- else
- return TRUE;
- }
- else if (SymNameMatches ("data_end"))
- {
- if (Program->DataSection)
- {
- NewSymbol = Program->DataSection->SectionSymbol;
- NewTargetOffset = Program->DataSection->Size;
- }
- else
- return TRUE;
- }
- else if (SymNameMatches ("data_size"))
- {
- if (Program->DataSection)
- {
- NewValue = Program->DataSection->Size;
- HasValue = TRUE;
- }
- else if (Program->ResolveAllBuiltins)
- HasValue = TRUE;
- }
- else if (SymNameMatches ("bss_start"))
- {
- if (Program->BSSSection)
- NewSymbol = Program->BSSSection->SectionSymbol;
- else
- return TRUE;
- }
- else if (SymNameMatches ("bss_end"))
- {
- if (Program->BSSSection)
- {
- NewSymbol = Program->BSSSection->SectionSymbol;
- NewTargetOffset = Program->BSSSection->Size;
- }
- else
- return TRUE;
- }
- else if (SymNameMatches ("bss_even_end"))
- {
- if (Program->BSSSection)
- {
- NewSymbol = Program->BSSSection->SectionSymbol;
- NewTargetOffset = (OFFSET) ((unsigned long) (Program->BSSSection->Size + 1) & ~1UL);
- }
- else
- return TRUE;
- }
- else if (SymNameMatches ("bss_size"))
- {
- if (Program->BSSSection)
- {
- NewValue = Program->BSSSection->Size;
- HasValue = TRUE;
- }
- else if (Program->ResolveAllBuiltins)
- HasValue = TRUE;
- }
- else if (SymNameMatches ("file_version"))
- {
- if (Program->ResolveAllBuiltins || Program->Version)
- {
- NewValue = Program->Version;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("link_time_year"))
- {
- if (Program->ResolveAllBuiltins)
- {
- NewValue = Program->LinkTime.Year;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("link_time_month"))
- {
- if (Program->ResolveAllBuiltins)
- {
- NewValue = Program->LinkTime.Month;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("link_time_day"))
- {
- if (Program->ResolveAllBuiltins)
- {
- NewValue = Program->LinkTime.Day;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("link_time_timestamp"))
- {
- if (Program->ResolveAllBuiltins)
- {
- NewValue = Program->LinkTime.LinkTime;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("kernel_flags"))
- {
- if (Program->ResolveAllBuiltins)
- {
- NewValue = Program->KernelFlags;
- HasValue = TRUE;
- }
- }
- else if (SymNameMatches ("kernel_bss_table"))
- {
- if (Program->BSSSection)
- {
- strcpy ((char *) (Location->SymbolName), "__kernel_bss_table");
- if (TryAgain)
- *TryAgain = TRUE;
- // This prevents the section from being merged, and prevents
- // relocs to it from being emitted.
- Program->BSSSection->Handled = TRUE;
- return FALSE;
- }
- else if (Program->ResolveAllBuiltins)
- SetToEntryPoint = TRUE;
- }
- else if (SymNameMatches ("program_size"))
- {
- if (Program->ResolveAllBuiltins && Program->MainSection)
- {
- NewValue = Program->MainSection->Size;
- HasValue = TRUE;
- }
- else
- return TRUE;
- }
- #ifdef FLASH_OS_SUPPORT
- else if (SymNameMatches ("archive_start"))
- {
- if (Program->ResolveAllBuiltins && Program->MainSection)
- {
- SetToEntryPoint = TRUE;
- NewValue = (OFFSET) ((unsigned long) (Program->MainSection->Size + 65535) & ~65535UL) - 0x02000;
- }
- else
- return TRUE;
- }
- #endif
- else if (SymNameMatches ("kernel_export_table"))
- {
- BOOLEAN HasExports = FALSE;
- for_each (TempSection, Program->Sections)
- {
- SYMBOL *TempSymbol;
- for_each (TempSymbol, TempSection->Symbols)
- {
- if (TempSymbol->Exported)
- {
- OFFSET ExportNumber = GetExportNumber (TempSymbol->Name);
- if (ExportNumber >= 0)
- {
- HasExports = TRUE;
- TempSection->Essential = TRUE;
- break;
- }
- }
- }
- }
-
- if (HasExports)
- {
- strcpy ((char *) (Location->SymbolName), "__kernel_export_table");
- if (TryAgain)
- *TryAgain = TRUE;
- return FALSE;
- }
- else if (Program->ResolveAllBuiltins)
- SetToEntryPoint = TRUE;
- }
- #ifdef DATA_VAR_SUPPORT
- else if (SymNameMatches ("data_var_name_end"))
- {
- // Point the reloc to the terminating zero byte of the name.
- if (Program->DataVarInfo->Name)
- {
- strcpy ((char *) (Location->SymbolName), "__data_var_name_start");
- Location->Offset += strlen (Program->DataVarInfo->Name) + 1;
- if (TryAgain)
- *TryAgain = TRUE;
- return FALSE;
- }
- }
- #endif /* DATA_VAR_SUPPORT */
- else
- return FALSE;
-
- if (!SetToEntryPoint)
- {
- if (HasValue)
- {
- // Point the location to the new value.
- Location->Symbol = NULL;
- FreeLocationSymbolName (Section, Location);
- Location->Offset += NewValue;
- }
- else if (NewSymbol)
- {
- // Point the location to the new symbol.
- Location->Symbol = NewSymbol;
- FreeLocationSymbolName (Section, Location);
- Location->Offset += NewTargetOffset;
- }
- else
- Location->Builtin = TRUE;
-
- return TRUE;
- }
- }
- // If this is a reloc to a kernel-specific symbol, point it to the
- // entry point. The result of this is that the reloc's value
- // becomes 0 if the reloc was made up by something like
- // _exit-__kernel_entry_point.
- else if (SymNameMatches ("exit") || SymNameMatches ("comment") || SymNameMatches ("extraram") || SymNameMatches ("library"))
- SetToEntryPoint = TRUE;
-
- if (SetToEntryPoint)
- {
- if (Program->EntryPoint.Symbol)
- {
- Location->Symbol = Program->EntryPoint.Symbol;
- FreeLocationSymbolName (Section, Location);
- Location->Offset += Program->EntryPoint.Offset + NewValue;
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
- }
- // Count the items for a specific built-in symbol, specified by SymName
- // and SymNameLength. If TrueValue is nonzero, items are not counted,
- // but NewValue is set to this value if at least one item was found. In
- // that case, if Program->ResolveAllBuiltins is false, NewValue may be
- // unchanged even though there are some items; you need to check back
- // later when Program->ResolveAllBuiltins is true.
- BOOLEAN GetBuiltinValue (PROGRAM *Program, const char *SymName, SIZE SymNameLength, OFFSET *NewValue, OFFSET TrueValue)
- {
- #define Count(n,op,code) \
- ({ \
- register OFFSET n__ = (n); \
- if (TrueValue) \
- { \
- if (n__) \
- { \
- *NewValue = TrueValue; \
- code; \
- } \
- } \
- else \
- *NewValue op n__; \
- })
- #define SetCounter(n) (Count ((n), =, (void) 0))
- #define IncreaseCounter(n) (Count ((n), +=, break))
-
- BOOLEAN SymNameMatches (const char *Name)
- {
- return (!(strncmp (SymName, Name, SymNameLength)));
- }
-
- SECTION *TempSection;
- RELOC *TempReloc;
- SYMBOL *TempSymbol;
-
- if (SymNameMatches ("constructor"))
- {
- if (Program->Constructors.Start && Program->Constructors.End)
- SetCounter ((Program->Constructors.End->Location - Program->Constructors.Start->Location) >> 2);
- }
- else if (SymNameMatches ("destructor"))
- {
- if (Program->Destructors.Start && Program->Destructors.End)
- SetCounter ((Program->Destructors.End->Location - Program->Destructors.Start->Location) >> 2);
- }
- else if (SymNameMatches ("reloc"))
- {
- // Count all absolute relocs.
- // Relative relocs will either be resolved completely or
- // produce errors.
- for_each (TempSection, Program->Sections)
- {
- IncreaseCounter (TempSection->Relocs.EmittedCount);
- // Since relocs may be removed, if ResolveAllBuiltins
- // is false, do not handle TrueValue.
- if ((!TrueValue) || Program->ResolveAllBuiltins)
- {
- for_each (TempReloc, TempSection->Relocs)
- if (!(TempReloc->Relative || TempReloc->Target.Builtin || (TempReloc->Target.Symbol && (TempReloc->Target.Symbol->Parent->Handled))))
- IncreaseCounter (1);
- }
- }
- }
- else if (SymNameMatches ("data_ref"))
- {
- if (Program->DataSection)
- {
- // Count all absolute relocs to the data section.
- for_each (TempSection, Program->Sections)
- for_each (TempReloc, TempSection->Relocs)
- if (TempReloc->Target.Symbol && (TempReloc->Target.Symbol->Parent == Program->DataSection) && (!(TempReloc->Relative || TempReloc->Target.Builtin)))
- IncreaseCounter (1);
- }
- }
- else if (SymNameMatches ("bss_ref"))
- {
- if (Program->BSSSection)
- {
- // Count all absolute relocs to the BSS section.
- for_each (TempSection, Program->Sections)
- for_each (TempReloc, TempSection->Relocs)
- if (TempReloc->Target.Symbol && (TempReloc->Target.Symbol->Parent == Program->BSSSection) && (!(TempReloc->Relative || TempReloc->Target.Builtin)))
- IncreaseCounter (1);
- }
- }
- else if (SymNameMatches ("rom_call"))
- {
- for_each (TempSection, Program->Sections)
- IncreaseCounter (CountItems (TempSection->ROMCalls, ROM_CALL));
- }
- else if (SymNameMatches ("ram_call"))
- {
- for_each (TempSection, Program->Sections)
- IncreaseCounter (CountItems (TempSection->RAMCalls, RAM_CALL));
- }
- else if (SymNameMatches ("lib"))
- SetCounter (CountItems (Program->Libraries, LIBRARY));
- else if (SymNameMatches ("referenced_lib"))
- SetCounter (Program->Libraries.ReferencedCount);
- else if (SymNameMatches ("export"))
- {
- // The number of exports is equal to the highest export number + 1.
- for_each (TempSection, Program->Sections)
- {
- for_each (TempSymbol, TempSection->Symbols)
- {
- if (TempSymbol->Exported)
- {
- OFFSET ExportNumber = GetExportNumber (TempSymbol->Name);
- if ((ExportNumber >= 0) && (*NewValue < ExportNumber + 1))
- Count (ExportNumber + 1, =, break);
- }
- }
- }
- }
- else if (SymNameMatches ("nostub_comment"))
- {
- for_each (TempSection, Program->Sections)
- {
- for_each (TempSymbol, TempSection->Symbols)
- {
- if (TempSymbol->Exported && (!(strncmp (TempSymbol->Name, SYMPF_NOSTUB_DATA, sizeof (SYMPF_NOSTUB_DATA) - 1))))
- {
- OFFSET ExportNumber = GetExportNumber (TempSymbol->Name + (sizeof (SYMPF_NOSTUB_DATA_START) - 1));
- if (ExportNumber >= 0)
- IncreaseCounter (1);
- }
- }
- }
- }
- else
- return FALSE;
-
- #undef IncreaseCounter
- #undef SetCounter
- #undef Count
-
- return TRUE;
- }
- // If the given symbol name belongs to a calculator-specific builtin
- // symbol, return a pointer to the part of it that holds the values.
- static const char *GetCalcBuiltinValues (const char *SymName)
- {
- if (!(strncmp (SymName, SYMPF_BUILTIN_CALC_CONST, sizeof (SYMPF_BUILTIN_CALC_CONST) - 1)))
- {
- return (SymName + (sizeof (SYMPF_BUILTIN_CALC_CONST) - 1));
- }
- return NULL;
- }
- // Check if the given location points to a calculator-specific builtin
- // symbol.
- BOOLEAN IsCalcBuiltinLocation (const LOCATION *Location)
- {
- return (Location->SymbolName && (GetCalcBuiltinValues (Location->SymbolName) || (!(strcmp (Location->SymbolName, SYM_BUILTIN_HARDWARE_ID)))));
- }
- // Return whether the reloc can be resolved to a calculator-specific value.
- // ResolveSpecialSymbol or something related must have been called on the
- // reloc at least once.
- BOOLEAN IsPlainCalcBuiltin (const RELOC *Reloc)
- {
- // To improve speed, check whether the target and relation (if it exists)
- // are builtin symbols.
- if (Reloc->Target.Builtin && ((!(Reloc->Relation)) || Reloc->Relation->Builtin))
- {
- // Check the target.
- if (IsCalcBuiltinLocation (&(Reloc->Target)))
- {
- // If there is a relation, check it.
- if (Reloc->Relation)
- return IsCalcBuiltinLocation (Reloc->Relation);
- // Otherwise, the reloc may not be relative, since that would
- // mean that it cannot be resolved to a number.
- else
- return (!(Reloc->Relative));
- }
- }
-
- return FALSE;
- }
- // If the location can be resolved to a calculator-specific value, get the
- // value for the specified calculator.
- // If IsCalcBuiltinLocation returned a positive result for this reloc, this
- // function will not return a negative result.
- BOOLEAN GetCalcBuiltinLocationValue (const LOCATION *Location, ProgramCalcs DestCalc, IMAX *Value)
- {
- // Basic sanity checks.
- if (Value && Location->SymbolName)
- {
- // Special case: __ld_hardware_id
- if (!(strcmp (Location->SymbolName, SYM_BUILTIN_HARDWARE_ID)))
- {
- switch (DestCalc)
- {
- case CALC_TI89:
- *Value = 3;
- break;
-
- case CALC_TI89 | CALC_FLAG_TITANIUM:
- *Value = 9;
- break;
-
- case CALC_TI92PLUS:
- *Value = 1;
- break;
-
- case CALC_V200:
- *Value = 8;
- break;
-
- default:
- Warning (NULL, SYM_BUILTIN_HARDWARE_ID " not defined for this calculator.");
- *Value = 0;
- }
- *Value += Location->Offset;
- return TRUE;
- }
- else
- {
- // Get the part of the symbol name that holds the values,
- // separated by '_'.
- const char *Values = GetCalcBuiltinValues (Location->SymbolName);
- if (Values)
- {
- // AND out the calculator flags.
- DestCalc &= ~CALC_FLAG_TITANIUM;
-
- // While we still have at least one value left...
- while (Values)
- {
- // Get the end of the value string.
- const char *ValueEnd = strchr (Values, '_');
- SIZE ValueSize = ValueEnd ? (SIZE) (ValueEnd - Values) : (SIZE) (strlen (Values));
-
- // If this is the value that belongs to the current calculator,
- // extract the value and return.
- if (DestCalc == 1)
- {
- char *EndPtr = NULL;
-
- // Create a copy of the value, with a terminating zero byte.
- char ValueStr[ValueSize+1];
- strncpy (ValueStr, Values, ValueSize);
- ValueStr [ValueSize] = 0;
-
- // Convert this string into a number and return it.
- *Value = strtoul (ValueStr, &EndPtr, 0);
- if (EndPtr && *EndPtr)
- Warning (NULL, "Invalid number `%s' in `%s'.", ValueStr, Location->SymbolName);
- *Value += Location->Offset;
-
- return TRUE;
- }
-
- // Advance to the next value.
- Values = ValueEnd ? ValueEnd + 1 : NULL;
- // Advance to the next calculator.
- DestCalc >>= 1;
- }
-
- // No more values were found, but the function did not exit yet.
- Warning (NULL, "Calculator constant `%s' contains too few values.", Location->SymbolName);
- *Value = 0;
-
- // We have to return a positive result anyway because
- // IsCalcBuiltinLocation would as well.
- return TRUE;
- }
- }
- }
-
- return FALSE;
- }
- // If the reloc can be resolved to a calculator-specific value, get the
- // value for the specified calculator.
- // The return value is the same as for IsPlainCalcBuiltin.
- BOOLEAN GetCalcBuiltinValue (const RELOC *Reloc, ProgramCalcs DestCalc, IMAX *Value)
- {
- if (Value)
- {
- // Get the value for the target.
- if (GetCalcBuiltinLocationValue (&(Reloc->Target), DestCalc, Value))
- {
- // If there is a relation, subtract its value.
- if (Reloc->Relation)
- {
- IMAX RelationValue;
- if (!(GetCalcBuiltinLocationValue (Reloc->Relation, DestCalc, &RelationValue)))
- return FALSE;
- *Value -= RelationValue;
- }
- // Otherwise, the reloc may not be relative
- // (see IsPlainCalcBuiltin).
- else if (Reloc->Relative)
- return FALSE;
-
- *Value += Reloc->FixedOffset;
- return TRUE;
- }
- }
-
- return FALSE;
- }
- // If required by some special symbol(s) at the end of the section,
- // modify the contents of the section.
- // This can be used to insert special items such as relocation entries.
- // MergedSection specifies the (usually large) part of the program that
- // has already been merged.
- // If necessary, MergedSection is frozen automatically.
- BOOLEAN HandleSectionContents (SECTION *Section, SECTION *MergedSection)
- {
- SYMBOL *Symbol;
-
- // Search the labels at the end of the secion to find special ones.
- for (Symbol = FindSymbolAtPos (Section, Section->Size, TRUE); Symbol; Symbol = GetNext (Symbol))
- {
- if (!(strncmp (Symbol->Name, SYMPF_BUILTIN_INSERT, sizeof (SYMPF_BUILTIN_INSERT) - 1)))
- return (HandleInsertion (Section, Symbol->Location, Symbol->Name + sizeof (SYMPF_BUILTIN_INSERT) - 1, MergedSection, FALSE));
- }
-
- return TRUE;
- }
- // Insert contents for an insertion specified by SymbolName, and return
- // a symbol from where the insertion took place.
- // If necessary, Section is frozen automatically.
- SYMBOL *HandleAutoInsertion (SECTION *Section, const char *SymbolName)
- {
- if (!(strncmp (SymbolName, SYMPF_BUILTIN_INSERT, sizeof (SYMPF_BUILTIN_INSERT) - 1)))
- {
- CreateSectionSegment (Section);
-
- // All insertions except compressed ones should be aligned on a 2-byte boundary.
- if ((!(strncmp (SymbolName, SYMPF_BUILTIN_INSERT_COMPRESSED, sizeof (SYMPF_BUILTIN_INSERT_COMPRESSED) - 1)))
- || (!(strncmp (SymbolName, SYMPF_BUILTIN_INSERT_MLINK, sizeof (SYMPF_BUILTIN_INSERT_MLINK) - 1)))
- || (!(strcmp (SymbolName, SYMPF_BUILTIN_INSERT "fargo021_relocs")))
- || (!(strcmp (SymbolName, SYMPF_BUILTIN_INSERT "preos_compressed_tables")))
- || PadSection (Section, 2))
- {
- // Create a new symbol at the end of the section.
- SYMBOL *Result = calloc (1, sizeof (SYMBOL));
-
- if (Result)
- {
- Result->Parent = Section;
- Result->Location = Section->Size;
- strncpy (Result->Name, SymbolName, MAX_SYM_LEN);
- Result->Exported = TRUE;
- Append (Section->Symbols, Result);
-
- // Insert the data.
- if (AppendInsertionData (Section, SymbolName + sizeof (SYMPF_BUILTIN_INSERT) - 1, Section, TRUE))
- return Result;
- }
- else
- Error (NULL, "Out of memory.");
- }
- }
-
- return NULL;
- }
- // Handle an insertion by cutting the section off at the specified location
- // and inserting the contents specified by the name, taking into account
- // that MergedSection specifies the (usually large) part of the program
- // that has already been merged.
- BOOLEAN HandleInsertion (SECTION *Section, OFFSET Location, const char *Name, SECTION *MergedSection, BOOLEAN AlwaysTerminate)
- {
- if (Location == Section->Size)
- return AppendInsertionData (Section, Name, MergedSection, AlwaysTerminate);
- else
- return TRUE;
- }
- // Append the data required by an insertion (specified by name) to the
- // section specified by Section, taking into account that MergedSection
- // specifies the (usually large) part of the program that has already
- // been merged.
- BOOLEAN AppendInsertionData (SECTION *Section, const char *Name, SECTION *MergedSection, BOOLEAN AlwaysTerminate)
- {
- BOOLEAN NameMatches (const char *InsertionName)
- {
- return (!(strcmp (Name, InsertionName)));
- }
-
- PROGRAM *Program = Section->Parent;
-
- #ifdef DATA_VAR_SUPPORT
- // Data variable name.
- if (NameMatches ("data_var_name"))
- return InsertDataVarName (Section);
- else
- #endif /* DATA_VAR_SUPPORT */
-
- // Nostub-specific formats.
- if (NameMatches ("nostub_comments"))
- return InsertNostubComments (Section);
-
- // Kernel-specific formats.
- else if (NameMatches ("kernel_relocs"))
- return InsertKernelRelocs (Section, NULL);
- else if (NameMatches ("kernel_bss_refs"))
- return InsertKernelSectionRefs (Section, Program->BSSSection, AlwaysTerminate);
- else if (NameMatches ("kernel_data_refs"))
- return InsertKernelSectionRefs (Section, Program->DataSection, AlwaysTerminate);
- else if (NameMatches ("kernel_rom_calls"))
- return InsertKernelROMCalls (Section);
- else if (NameMatches ("kernel_ram_calls"))
- return InsertKernelRAMCalls (Section);
- else if (NameMatches ("kernel_libs"))
- return InsertKernelLibraries (Section);
- else if (NameMatches ("kernel_exports"))
- return InsertKernelExports (Section, TRUE);
-
- #ifdef FARGO_SUPPORT
- // Fargo-specific formats.
- else if (NameMatches ("fargo_exports"))
- return InsertKernelExports (Section, FALSE);
- else if (NameMatches ("fargo020_bss_refs"))
- return InsertKernelSectionRefs (Section, Program->BSSSection, TRUE);
- else if (NameMatches ("fargo020_libs"))
- return InsertFargo020Libraries (Section);
- #endif /* FARGO_SUPPORT */
-
- // PreOS-specific formats.
- else if (NameMatches ("preos_compressed_tables"))
- return InsertPreOsCompressedTables (Section);
-
- // Other compressed formats.
- else
- {
- char *ReferenceName = malloc ((sizeof (SYMPF_BUILTIN) - 1) + strlen (Name) + sizeof ("_ref"));
-
- if (ReferenceName)
- {
- // Build the reference symbol name: "__ld_" Name "_ref".
- strcpy (ReferenceName, SYMPF_BUILTIN);
- strcat (ReferenceName, Name);
- strcat (ReferenceName, "_ref");
-
- {
- LOCATION Reference = {NULL, ReferenceName, 0, FALSE};
-
- // Try to find a reference symbol. If none is found, use
- // the program entry point.
- Section->Relocs.UnresolvedCount++;
- if (!(ResolveLocation (Program, Section, &Reference)))
- {
- FreeLocationSymbolName (Section, &Reference);
- Reference = Program->EntryPoint;
- }
-
- #ifdef FARGO_SUPPORT
- // Fargo-specific formats.
- if (NameMatches ("fargo021_relocs"))
- return InsertCompressedRelocs (Section, NULL, MergedSection, &Reference);
- else if (NameMatches ("fargo021_bss_refs"))
- return InsertFargo021SectionRefs (Section, Program->BSSSection, MergedSection, &Reference);
- else if (NameMatches ("fargo021_libs"))
- return InsertFargo021Libraries (Section, MergedSection, &Reference);
- #endif /* FARGO_SUPPORT */
-
- // Compressed relocation tables using our own format.
- else if (NameMatches ("compressed_relocs"))
- return InsertCompressedRelocs (Section, NULL, MergedSection, &Reference);
- else if (NameMatches ("compressed_bss_refs"))
- return InsertCompressedSectionRefs (Section, Program->BSSSection, MergedSection, &Reference);
- else if (NameMatches ("compressed_data_refs"))
- return InsertCompressedSectionRefs (Section, Program->DataSection, MergedSection, &Reference);
- else if (NameMatches ("compressed_rom_calls"))
- return InsertCompressedROMCalls (Section, MergedSection, &Reference);
-
- // Compressed relocation tables using our own mlink-style format.
- else if (NameMatches ("mlink_relocs"))
- return InsertMlinkRelocs (Section, NULL, MergedSection, &Reference);
- else if (NameMatches ("mlink_bss_refs"))
- return InsertMlinkSectionRefs (Section, Program->BSSSection, MergedSection, &Reference);
- else if (NameMatches ("mlink_data_refs"))
- return InsertMlinkSectionRefs (Section, Program->DataSection, MergedSection, &Reference);
- else if (NameMatches ("mlink_rom_calls"))
- return InsertMlinkROMCalls (Section, MergedSection, &Reference);
-
- else
- Warning (GetFileName (Section, Section->Size), "Unrecognized insertion `%s'.", Name);
- }
- }
- else
- {
- Error (NULL, "Out of memory.");
- return FALSE;
- }
- }
-
- return TRUE;
- }
|