forked from OSchip/llvm-project
				
			[ELF] Support for symbol assignment in linker scripts within SECTIONS {} block
llvm-svn: 275158
This commit is contained in:
		
							parent
							
								
									425175934e
								
							
						
					
					
						commit
						eda81a1b86
					
				| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#include "OutputSections.h"
 | 
			
		||||
#include "ScriptParser.h"
 | 
			
		||||
#include "Strings.h"
 | 
			
		||||
#include "Symbols.h"
 | 
			
		||||
#include "SymbolTable.h"
 | 
			
		||||
#include "Target.h"
 | 
			
		||||
#include "llvm/ADT/StringSwitch.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -226,16 +227,25 @@ void LinkerScript<ELFT>::assignAddresses(
 | 
			
		|||
  uintX_t ThreadBssOffset = 0;
 | 
			
		||||
 | 
			
		||||
  for (SectionsCommand &Cmd : Opt.Commands) {
 | 
			
		||||
    if (Cmd.Kind == ExprKind) {
 | 
			
		||||
    switch (Cmd.Kind) {
 | 
			
		||||
    case ExprKind:
 | 
			
		||||
      Dot = evalExpr(Cmd.Expr, Dot);
 | 
			
		||||
      continue;
 | 
			
		||||
    case SymbolAssignmentKind: {
 | 
			
		||||
      auto *D =
 | 
			
		||||
          cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd.Name));
 | 
			
		||||
      D->Value = evalExpr(Cmd.Expr, Dot);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Find all the sections with required name. There can be more than
 | 
			
		||||
    // ont section with such name, if the alignment, flags or type
 | 
			
		||||
    // attribute differs.
 | 
			
		||||
    for (OutputSectionBase<ELFT> *Sec : Sections) {
 | 
			
		||||
      if (Sec->getName() != Cmd.SectionName)
 | 
			
		||||
      if (Sec->getName() != Cmd.Name)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
 | 
			
		||||
| 
						 | 
				
			
			@ -283,7 +293,7 @@ int LinkerScript<ELFT>::getSectionIndex(StringRef Name) {
 | 
			
		|||
  auto Begin = Opt.Commands.begin();
 | 
			
		||||
  auto End = Opt.Commands.end();
 | 
			
		||||
  auto I = std::find_if(Begin, End, [&](SectionsCommand &N) {
 | 
			
		||||
    return N.Kind == SectionKind && N.SectionName == Name;
 | 
			
		||||
    return N.Kind == SectionKind && N.Name == Name;
 | 
			
		||||
  });
 | 
			
		||||
  return I == End ? INT_MAX : (I - Begin);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +309,13 @@ int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
 | 
			
		|||
  return I < J ? -1 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
void LinkerScript<ELFT>::addScriptedSymbols() {
 | 
			
		||||
  for (SectionsCommand &Cmd : Opt.Commands)
 | 
			
		||||
    if (Cmd.Kind == SymbolAssignmentKind)
 | 
			
		||||
      Symtab<ELFT>::X->addAbsolute(Cmd.Name, STV_DEFAULT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class elf::ScriptParser : public ScriptParserBase {
 | 
			
		||||
  typedef void (ScriptParser::*Handler)();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -323,7 +340,9 @@ private:
 | 
			
		|||
  void readSections();
 | 
			
		||||
 | 
			
		||||
  void readLocationCounterValue();
 | 
			
		||||
  void readOutputSectionDescription();
 | 
			
		||||
  void readOutputSectionDescription(StringRef OutSec);
 | 
			
		||||
  void readSymbolAssignment(StringRef Name);
 | 
			
		||||
  std::vector<StringRef> readSectionsCommandExpr();
 | 
			
		||||
 | 
			
		||||
  const static StringMap<Handler> Cmd;
 | 
			
		||||
  ScriptConfiguration &Opt = *ScriptConfig;
 | 
			
		||||
| 
						 | 
				
			
			@ -487,30 +506,29 @@ void ScriptParser::readSections() {
 | 
			
		|||
  expect("{");
 | 
			
		||||
  while (!Error && !skip("}")) {
 | 
			
		||||
    StringRef Tok = peek();
 | 
			
		||||
    if (Tok == ".")
 | 
			
		||||
    if (Tok == ".") {
 | 
			
		||||
      readLocationCounterValue();
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    next();
 | 
			
		||||
    if (peek() == "=")
 | 
			
		||||
      readSymbolAssignment(Tok);
 | 
			
		||||
    else
 | 
			
		||||
      readOutputSectionDescription();
 | 
			
		||||
      readOutputSectionDescription(Tok);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ScriptParser::readLocationCounterValue() {
 | 
			
		||||
  expect(".");
 | 
			
		||||
  expect("=");
 | 
			
		||||
  Opt.Commands.push_back({ExprKind, {}, ""});
 | 
			
		||||
  SectionsCommand &Cmd = Opt.Commands.back();
 | 
			
		||||
  while (!Error) {
 | 
			
		||||
    StringRef Tok = next();
 | 
			
		||||
    if (Tok == ";")
 | 
			
		||||
      break;
 | 
			
		||||
    Cmd.Expr.push_back(Tok);
 | 
			
		||||
  }
 | 
			
		||||
  if (Cmd.Expr.empty())
 | 
			
		||||
  std::vector<StringRef> Expr = readSectionsCommandExpr();
 | 
			
		||||
  if (Expr.empty())
 | 
			
		||||
    error("error in location counter expression");
 | 
			
		||||
  else
 | 
			
		||||
    Opt.Commands.push_back({ExprKind, std::move(Expr), ""});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ScriptParser::readOutputSectionDescription() {
 | 
			
		||||
  StringRef OutSec = next();
 | 
			
		||||
void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
 | 
			
		||||
  Opt.Commands.push_back({SectionKind, {}, OutSec});
 | 
			
		||||
  expect(":");
 | 
			
		||||
  expect("{");
 | 
			
		||||
| 
						 | 
				
			
			@ -548,6 +566,26 @@ void ScriptParser::readOutputSectionDescription() {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ScriptParser::readSymbolAssignment(StringRef Name) {
 | 
			
		||||
  expect("=");
 | 
			
		||||
  std::vector<StringRef> Expr = readSectionsCommandExpr();
 | 
			
		||||
  if (Expr.empty())
 | 
			
		||||
    error("error in symbol assignment expression");
 | 
			
		||||
  else
 | 
			
		||||
    Opt.Commands.push_back({SymbolAssignmentKind, std::move(Expr), Name});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
 | 
			
		||||
  std::vector<StringRef> Expr;
 | 
			
		||||
  while (!Error) {
 | 
			
		||||
    StringRef Tok = next();
 | 
			
		||||
    if (Tok == ";")
 | 
			
		||||
      break;
 | 
			
		||||
    Expr.push_back(Tok);
 | 
			
		||||
  }
 | 
			
		||||
  return Expr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool isUnderSysroot(StringRef Path) {
 | 
			
		||||
  if (Config->Sysroot == "")
 | 
			
		||||
    return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,12 +40,12 @@ struct SectionRule {
 | 
			
		|||
// This enum represents what we can observe in SECTIONS tag of script:
 | 
			
		||||
// ExprKind is a location counter change, like ". = . + 0x1000"
 | 
			
		||||
// SectionKind is a description of output section, like ".data :..."
 | 
			
		||||
enum SectionsCommandKind { ExprKind, SectionKind };
 | 
			
		||||
enum SectionsCommandKind { ExprKind, SectionKind, SymbolAssignmentKind };
 | 
			
		||||
 | 
			
		||||
struct SectionsCommand {
 | 
			
		||||
  SectionsCommandKind Kind;
 | 
			
		||||
  std::vector<StringRef> Expr;
 | 
			
		||||
  StringRef SectionName;
 | 
			
		||||
  StringRef Name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ScriptConfiguration holds linker script parse results.
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +81,7 @@ public:
 | 
			
		|||
  bool shouldKeep(InputSectionBase<ELFT> *S);
 | 
			
		||||
  void assignAddresses(ArrayRef<OutputSectionBase<ELFT> *> S);
 | 
			
		||||
  int compareSections(StringRef A, StringRef B);
 | 
			
		||||
  void addScriptedSymbols();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  // "ScriptConfig" is a bit too long, so define a short name for it.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -786,6 +786,10 @@ template <class ELFT> void Writer<ELFT>::createSections() {
 | 
			
		|||
  // Define __rel[a]_iplt_{start,end} symbols if needed.
 | 
			
		||||
  addRelIpltSymbols();
 | 
			
		||||
 | 
			
		||||
  // Add scripted symbols with zero values now.
 | 
			
		||||
  // Real values will be assigned later
 | 
			
		||||
  Script<ELFT>::X->addScriptedSymbols();
 | 
			
		||||
 | 
			
		||||
  if (!Out<ELFT>::EhFrame->empty()) {
 | 
			
		||||
    OutputSections.push_back(Out<ELFT>::EhFrame);
 | 
			
		||||
    Out<ELFT>::EhFrame->finalize();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
# REQUIRES: x86
 | 
			
		||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
 | 
			
		||||
 | 
			
		||||
# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
 | 
			
		||||
# RUN: ld.lld -o %t1 --script %t.script %t
 | 
			
		||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
 | 
			
		||||
# CHECK: 0000000000000121         *ABS*    00000000 text_end
 | 
			
		||||
 | 
			
		||||
.global _start
 | 
			
		||||
_start:
 | 
			
		||||
 nop
 | 
			
		||||
		Loading…
	
		Reference in New Issue