void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an imported symbol */ { if (S->Flags & SF_DEFINED) { Error ("Symbol `%m%p' is already defined", GetSymName (S)); S->Flags |= SF_MULTDEF; return; } if (S->Flags & SF_EXPORT) { /* The symbol is already marked as exported symbol */ Error ("Cannot import exported symbol `%m%p'", GetSymName (S)); return; } /* If no address size is given, use the address size of the enclosing ** segment. */ if (AddrSize == ADDR_SIZE_DEFAULT) { AddrSize = GetCurrentSegAddrSize (); } /* If the symbol is marked as import or global, check the address size, ** then do silently remove the global flag. */ if (S->Flags & SF_IMPORT) { if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) { Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S)); } if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } if (S->Flags & SF_GLOBAL) { S->Flags &= ~SF_GLOBAL; if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } /* Set the symbol data */ S->Flags |= (SF_IMPORT | Flags); S->AddrSize = AddrSize; /* Mark the position of the import as the position of the definition. ** Please note: In case of multiple .global or .import statements, the line ** infos add up. */ GetFullLineInfo (&S->DefLines); }
int IsSizeOfSymbol (const SymEntry* Sym) /* Return true if the given symbol is the one that encodes the size of some * entity. Sym may also be a NULL pointer in which case false is returned. */ { return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0); }
void SymDump (FILE* F) /* Dump the symbol table */ { SymEntry* S = SymList; while (S) { /* Ignore unused symbols */ if ((S->Flags & SF_UNUSED) == 0) { fprintf (F, "%-24s %s %s %s %s %s\n", SB_GetConstBuf (GetSymName (S)), (S->Flags & SF_DEFINED)? "DEF" : "---", (S->Flags & SF_REFERENCED)? "REF" : "---", (S->Flags & SF_IMPORT)? "IMP" : "---", (S->Flags & SF_EXPORT)? "EXP" : "---", AddrSizeToStr (S->AddrSize)); } /* Next symbol */ S = S->List; } }
void SymCheck (void) /* Run through all symbols and check for anomalies and errors */ { SymEntry* S; /* Check for open scopes */ if (CurrentScope->Parent != 0) { Error ("Local scope was not closed"); } /* First pass: Walk through all symbols, checking for undefined's and ** changing them to trampoline symbols or make them imports. */ S = SymList; while (S) { /* If the symbol is marked as global, mark it as export, if it is ** already defined, otherwise mark it as import. */ if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_DEFINED) { SymExportFromGlobal (S); } else { SymImportFromGlobal (S); } } /* Handle undefined symbols */ if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) { /* This is an undefined symbol. Handle it. */ SymCheckUndefined (S); } /* Next symbol */ S = S->List; } /* Second pass: Walk again through the symbols. Count exports and imports ** and set address sizes where this has not happened before. Ignore ** undefined's, since we handled them in the last pass, and ignore unused ** symbols, since we handled them in the last pass, too. */ S = SymList; while (S) { if ((S->Flags & SF_UNUSED) == 0 && (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) { /* Check for defined symbols that were never referenced */ if (IsSizeOfSymbol (S)) { /* Remove line infos, we don't need them any longer */ ReleaseFullLineInfo (&S->DefLines); ReleaseFullLineInfo (&S->RefLines); } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) { LIWarning (&S->DefLines, 2, "Symbol `%m%p' is defined but never used", GetSymName (S)); } /* Assign an index to all imports */ if (S->Flags & SF_IMPORT) { if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { /* Imported symbol is not referenced */ LIWarning (&S->DefLines, 2, "Symbol `%m%p' is imported but never used", GetSymName (S)); } else { /* Give the import an id, count imports */ S->ImportId = ImportCount++; } } /* Count exports, assign the export ID */ if (S->Flags & SF_EXPORT) { S->ExportId = ExportCount++; } /* If the symbol is defined but has an unknown address size, ** recalculate it. */ if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) { ExprDesc ED; ED_Init (&ED); StudyExpr (S->Expr, &ED); S->AddrSize = ED.AddrSize; if (SymIsExport (S)) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real export size */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&S->DefLines, 1, "Symbol `%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } ED_Done (&ED); } /* If the address size of the symbol was guessed, check the guess ** against the actual address size and print a warning if the two ** differ. */ if (S->AddrSize != ADDR_SIZE_DEFAULT) { /* Do we have data for this address size? */ if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) { /* Get the file position where the symbol was used */ const FilePos* P = S->GuessedUse[S->AddrSize - 1]; if (P) { PWarning (P, 0, "Didn't use %s addressing for `%m%p'", AddrSizeToStr (S->AddrSize), GetSymName (S)); } } } } /* Next symbol */ S = S->List; } }
static void SymCheckUndefined (SymEntry* S) /* Handle an undefined symbol */ { /* Undefined symbol. It may be... ** ** - An undefined symbol in a nested lexical level. If the symbol is not ** fixed to this level, search for the symbol in the higher levels and ** make the entry a trampoline entry if we find one. ** ** - If the symbol is not found, it is a real undefined symbol. If the ** AutoImport flag is set, make it an import. If the AutoImport flag is ** not set, it's an error. */ SymEntry* Sym = 0; if ((S->Flags & SF_FIXED) == 0) { SymTable* Tab = GetSymParentScope (S); while (Tab) { Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY); if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) { /* We've found a symbol in a higher level that is ** either defined in the source, or an import. */ break; } /* No matching symbol found in this level. Look further */ Tab = Tab->Parent; } } if (Sym) { /* We found the symbol in a higher level. Transfer the flags and ** address size from the local symbol to that in the higher level ** and check for problems. */ if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { /* The symbol is already marked as import */ LIError (&S->RefLines, "Symbol `%s' is already an import", GetString (Sym->Name)); } if ((Sym->Flags & SF_EXPORT) == 0) { /* Mark the symbol as an export */ Sym->Flags |= SF_EXPORT; Sym->ExportSize = S->ExportSize; if (Sym->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the actual size of the symbol */ Sym->ExportSize = Sym->AddrSize; } if (Sym->AddrSize > Sym->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&Sym->DefLines, 1, "Symbol `%m%p' is %s but exported %s", GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), AddrSizeToStr (Sym->ExportSize)); } } } if (S->Flags & SF_REFERENCED) { /* Mark as referenced and move the line info */ Sym->Flags |= SF_REFERENCED; CollTransfer (&Sym->RefLines, &S->RefLines); CollDeleteAll (&S->RefLines); } /* Transfer all expression references */ SymTransferExprRefs (S, Sym); /* Mark the symbol as unused removing all other flags */ S->Flags = SF_UNUSED; } else { /* The symbol is definitely undefined */ if (S->Flags & SF_EXPORT) { /* We will not auto-import an export */ LIError (&S->RefLines, "Exported symbol `%m%p' was never defined", GetSymName (S)); } else { if (AutoImport) { /* Mark as import, will be indexed later */ S->Flags |= SF_IMPORT; /* Use the address size for code */ S->AddrSize = CodeAddrSize; /* Mark point of import */ GetFullLineInfo (&S->DefLines); } else { /* Error */ LIError (&S->RefLines, "Symbol `%m%p' is undefined", GetSymName (S)); } } } }
STATIC BOOLEAN WriteSections32 ( SECTION_FILTER_TYPES FilterType ) { UINT32 Idx; Elf_Shdr *SecShdr; UINT32 SecOffset; BOOLEAN (*Filter)(Elf_Shdr *); // // Initialize filter pointer // switch (FilterType) { case SECTION_TEXT: Filter = IsTextShdr; break; case SECTION_HII: Filter = IsHiiRsrcShdr; break; case SECTION_DATA: Filter = IsDataShdr; break; default: return FALSE; } // // First: copy sections. // for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { Elf_Shdr *Shdr = GetShdrByIndex(Idx); if ((*Filter)(Shdr)) { switch (Shdr->sh_type) { case SHT_PROGBITS: /* Copy. */ memcpy(mCoffFile + mCoffSectionsOffset[Idx], (UINT8*)mEhdr + Shdr->sh_offset, Shdr->sh_size); break; case SHT_NOBITS: memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size); break; default: // // Ignore for unkown section type. // VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type); break; } } } // // Second: apply relocations. // for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { // // Determine if this is a relocation section. // Elf_Shdr *RelShdr = GetShdrByIndex(Idx); if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) { continue; } // // Relocation section found. Now extract section information that the relocations // apply to in the ELF data and the new COFF data. // SecShdr = GetShdrByIndex(RelShdr->sh_info); SecOffset = mCoffSectionsOffset[RelShdr->sh_info]; // // Only process relocations for the current filter type. // if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { UINT32 RelOffset; // // Determine the symbol table referenced by the relocation data. // Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset; // // Process all relocation entries for this section. // for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) { // // Set pointer to relocation entry // Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset); // // Set pointer to symbol table entry associated with the relocation entry. // Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); Elf_Shdr *SymShdr; UINT8 *Targ; UINT16 Address; // // Check section header index found in symbol table and get the section // header location. // if (Sym->st_shndx == SHN_UNDEF || Sym->st_shndx >= mEhdr->e_shnum) { const UINT8 *SymName = GetSymName(Sym); if (SymName == NULL) { SymName = (const UINT8 *)"<unknown>"; } Error (NULL, 0, 3000, "Invalid", "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type. " "For example, absolute and undefined symbols are not supported.", mInImageName, SymName, Sym->st_value); exit(EXIT_FAILURE); } SymShdr = GetShdrByIndex(Sym->st_shndx); // // Convert the relocation data to a pointer into the coff file. // // Note: // r_offset is the virtual address of the storage unit to be relocated. // sh_addr is the virtual address for the base of the section. // Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); // // Determine how to handle each relocation type based on the machine type. // if (mEhdr->e_machine == EM_386) { switch (ELF_R_TYPE(Rel->r_info)) { case R_386_NONE: break; case R_386_32: // // Absolute relocation. // Converts Targ from a absolute virtual address to the absolute // COFF address. // *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; break; case R_386_PC32: // // Relative relocation: Symbol - Ip + Addend // *(UINT32 *)Targ = *(UINT32 *)Targ + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) - (SecOffset - SecShdr->sh_addr); break; default: Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } } else if (mEhdr->e_machine == EM_ARM) { switch (ELF32_R_TYPE(Rel->r_info)) { case R_ARM_RBASE: // No relocation - no action required // break skipped case R_ARM_PC24: case R_ARM_REL32: case R_ARM_XPC25: case R_ARM_THM_PC22: case R_ARM_THM_JUMP19: case R_ARM_CALL: case R_ARM_JMP24: case R_ARM_THM_JUMP24: case R_ARM_PREL31: case R_ARM_MOVW_PREL_NC: case R_ARM_MOVT_PREL: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: case R_ARM_THM_JMP6: case R_ARM_THM_ALU_PREL_11_0: case R_ARM_THM_PC12: case R_ARM_REL32_NOI: case R_ARM_ALU_PC_G0_NC: case R_ARM_ALU_PC_G0: case R_ARM_ALU_PC_G1_NC: case R_ARM_ALU_PC_G1: case R_ARM_ALU_PC_G2: case R_ARM_LDR_PC_G1: case R_ARM_LDR_PC_G2: case R_ARM_LDRS_PC_G0: case R_ARM_LDRS_PC_G1: case R_ARM_LDRS_PC_G2: case R_ARM_LDC_PC_G0: case R_ARM_LDC_PC_G1: case R_ARM_LDC_PC_G2: case R_ARM_GOT_PREL: case R_ARM_THM_JUMP11: case R_ARM_THM_JUMP8: case R_ARM_TLS_GD32: case R_ARM_TLS_LDM32: case R_ARM_TLS_IE32: // Thease are all PC-relative relocations and don't require modification // GCC does not seem to have the concept of a application that just needs to get relocated. break; case R_ARM_THM_MOVW_ABS_NC: // MOVW is only lower 16-bits of the addres Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); break; case R_ARM_THM_MOVT_ABS: // MOVT is only upper 16-bits of the addres Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16); ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); break; case R_ARM_ABS32: case R_ARM_TARGET1: case R_ARM_RABS32: // // Absolute relocation. // *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; break; default: Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info)); } } } } }
void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio) /* Mark the given symbol as a module constructor/destructor. This will also ** mark the symbol as an export. Initializers may never be zero page symbols. */ { /* Check the parameters */ #if (CD_TYPE_MIN != 0) CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); #else CHECK (Type <= CD_TYPE_MAX); #endif CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX); /* Check for errors */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ Error ("Symbol `%m%p' is already an import", GetSymName (S)); return; } if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported or imported */ Error ("Var symbol `%m%p' cannot be exported", GetSymName (S)); return; } /* If the symbol was already marked as an export or global, check if ** this was done specifiying the same address size. In case of a global ** declaration, silently remove the global flag. */ if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } S->Flags &= ~SF_GLOBAL; } S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the ** exported size. */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } /* If the symbol already was declared as a condes of this type, ** check if the new priority value is the same as the old one. */ if (S->ConDesPrio[Type] != CD_PRIO_NONE) { if (S->ConDesPrio[Type] != Prio) { Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S)); } } S->ConDesPrio[Type] = Prio; /* Set the symbol data */ S->Flags |= (SF_EXPORT | SF_REFERENCED); /* Remember the line info for this reference */ CollAppend (&S->RefLines, GetAsmLineInfo ()); }
void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as a global symbol, that is, as a symbol that is ** either imported or exported. */ { if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported or imported */ Error ("Var symbol `%m%p' cannot be made global", GetSymName (S)); return; } /* If the symbol is already marked as import, the address size must match. ** Apart from that, ignore the global declaration. */ if (S->Flags & SF_IMPORT) { if (AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ AddrSize = GetCurrentSegAddrSize (); } if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } return; } /* If the symbol is already an export: If it is not defined, the address ** sizes must match. */ if (S->Flags & SF_EXPORT) { if ((S->Flags & SF_DEFINED) == 0) { /* Symbol is undefined */ if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } else if (AddrSize != ADDR_SIZE_DEFAULT) { /* Symbol is defined and address size given */ if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } return; } /* If the symbol is already marked as global, the address size must match. ** Use the ExportSize here, since it contains the actual address size ** passed to this function. */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } return; } /* If we come here, the symbol was neither declared as export, import or ** global before. Check if it is already defined, in which case it will ** become an export. If it is not defined, mark it as global and remember ** the given address sizes. */ if (S->Flags & SF_DEFINED) { /* The symbol is defined, export it */ S->ExportSize = AddrSize; if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* No export size given, use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol `%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } S->Flags |= (SF_EXPORT | Flags); } else { /* Since we don't know if the symbol will get exported or imported, ** remember two different address sizes: One for an import in AddrSize, ** and the other one for an export in ExportSize. */ S->AddrSize = AddrSize; if (S->AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ S->AddrSize = GetCurrentSegAddrSize (); } S->ExportSize = AddrSize; S->Flags |= (SF_GLOBAL | Flags); /* Remember the current location as location of definition in case ** an .IMPORT follows later. */ GetFullLineInfo (&S->DefLines); } }
void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an exported symbol */ { /* Check if it's ok to export the symbol */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ Error ("Symbol `%m%p' is already an import", GetSymName (S)); return; } if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported */ Error ("Var symbol `%m%p' cannot be exported", GetSymName (S)); return; } /* If the symbol was marked as global before, remove the global flag and ** proceed, but check the address size. */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } S->Flags &= ~SF_GLOBAL; /* .GLOBAL remembers line infos in case an .IMPORT follows. We have ** to remove these here. */ ReleaseFullLineInfo (&S->DefLines); } /* If the symbol was already marked as an export, but wasn't defined ** before, the address sizes in both definitions must match. */ if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol `%m%p'", GetSymName (S)); } } S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the ** exported size. */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* No export size given, use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol `%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } /* Set the symbol data */ S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags); /* Remember line info for this reference */ CollAppend (&S->RefLines, GetAsmLineInfo ()); }
void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags) /* Define a new symbol */ { if (S->Flags & SF_IMPORT) { /* Defined symbol is marked as imported external symbol */ Error ("Symbol `%m%p' is already an import", GetSymName (S)); return; } if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) { /* Variable symbols cannot be exports or globals */ Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S)); return; } if (S->Flags & SF_DEFINED) { /* Multiple definition. In case of a variable, this is legal. */ if ((S->Flags & SF_VAR) == 0) { Error ("Symbol `%m%p' is already defined", GetSymName (S)); S->Flags |= SF_MULTDEF; return; } else { /* Redefinition must also be a variable symbol */ if ((Flags & SF_VAR) == 0) { Error ("Symbol `%m%p' is already different kind", GetSymName (S)); return; } /* Delete the current symbol expression, since it will get ** replaced */ FreeExpr (S->Expr); S->Expr = 0; } } /* Map a default address size to a real value */ if (AddrSize == ADDR_SIZE_DEFAULT) { /* ### Must go! Delay address size calculation until end of assembly! */ ExprDesc ED; ED_Init (&ED); StudyExpr (Expr, &ED); AddrSize = ED.AddrSize; ED_Done (&ED); } /* Set the symbol value */ S->Expr = Expr; /* In case of a variable symbol, walk over all expressions containing ** this symbol and replace the (sub-)expression by the literal value of ** the tree. Be sure to replace the expression node in place, since there ** may be pointers to it. */ if (Flags & SF_VAR) { SymReplaceExprRefs (S); } /* If the symbol is marked as global, export it. Address size is checked ** below. */ if (S->Flags & SF_GLOBAL) { S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT; ReleaseFullLineInfo (&S->DefLines); } /* Mark the symbol as defined and use the given address size */ S->Flags |= (SF_DEFINED | Flags); S->AddrSize = AddrSize; /* Remember the line info of the symbol definition */ GetFullLineInfo (&S->DefLines); /* If the symbol is exported, check the address sizes */ if (S->Flags & SF_EXPORT) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol `%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } /* If this is not a local symbol, remember it as the last global one */ if ((S->Flags & SF_LOCAL) == 0) { SymLast = S; } }