From 77afbdce53aa740777486b0cc4e9df151ae65468 Mon Sep 17 00:00:00 2001 From: Jack Carter Date: Tue, 19 Feb 2013 21:57:35 +0000 Subject: [PATCH] ELF symbol table field st_other support, excluding visibility bits. Generic STO handling at the Target level. The st_other field of the ELF symbol table is one byte in size. The first 2 bytes are used for generic visibility and are currently handled by llvm. The other six bits are processor specific and need to be set at the target level. A couple of notes: The new static methods for accessing and setting the "other" flags in include/llvm/MC/MCELF.h match the style guide and not the other methods in the file. I don't like the inconsistency, but feel I should follow the prescribed lowerUpper() convention. STO_ value definitions are not specified in gnu land as consistently as the STT_ and STB_ fields. Probably because the latter were defined in a standards doc and the former defined partially in code. I have stuck with the full byte definition of the flags. Contributer: Zoran Jovanovic git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175561 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCELF.h | 2 ++ include/llvm/MC/MCELFStreamer.h | 2 ++ include/llvm/MC/MCStreamer.h | 4 ++++ lib/MC/ELFObjectWriter.cpp | 11 ++++++++--- lib/MC/MCELF.cpp | 15 +++++++++++++++ lib/MC/MCELFStreamer.cpp | 4 ++++ lib/MC/MCStreamer.cpp | 5 +++++ 7 files changed, 40 insertions(+), 3 deletions(-) diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h index e08f1e65429..7e59911a89c 100644 --- a/include/llvm/MC/MCELF.h +++ b/include/llvm/MC/MCELF.h @@ -28,6 +28,8 @@ class MCELF { static unsigned GetType(const MCSymbolData &SD); static void SetVisibility(MCSymbolData &SD, unsigned Visibility); static unsigned GetVisibility(MCSymbolData &SD); + static void setOther(MCSymbolData &SD, unsigned Other); + static unsigned getOther(MCSymbolData &SD); }; } diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index f78de157013..6fb2d22be2e 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -65,6 +65,8 @@ public: virtual void EmitCOFFSymbolType(int Type); virtual void EndCOFFSymbolDef(); + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 9bc4a8bbb51..d247066cd9f 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCWin64EH.h" @@ -286,6 +287,9 @@ namespace llvm { /// a Thumb mode function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func) = 0; + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// /// This corresponds to an assembler statement such as: diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index fb14dc96b39..0b97f2700be 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -546,12 +546,17 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || Data.getSymbol().isVariable(); + // Binding and Type share the same byte as upper and lower nibbles uint8_t Binding = MCELF::GetBinding(OrigData); - uint8_t Visibility = MCELF::GetVisibility(OrigData); uint8_t Type = MCELF::GetType(Data); - uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); - uint8_t Other = Visibility; + + // Other and Visibility share the same byte with Visability using the lower + // 2 bits + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Other = MCELF::getOther(OrigData) << + (ELF_Other_Shift - ELF_STV_Shift); + Other |= Visibility; uint64_t Value = SymbolValue(Data, Layout); uint64_t Size = 0; diff --git a/lib/MC/MCELF.cpp b/lib/MC/MCELF.cpp index 4db2846bc3d..560cdbc6aba 100644 --- a/lib/MC/MCELF.cpp +++ b/lib/MC/MCELF.cpp @@ -52,6 +52,8 @@ unsigned MCELF::GetType(const MCSymbolData &SD) { return Type; } +// Visibility is stored in the first two bits of st_other +// st_other values are stored in the second byte of get/setFlags void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) { assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); @@ -68,4 +70,17 @@ unsigned MCELF::GetVisibility(MCSymbolData &SD) { return Visibility; } +// Other is stored in the last six bits of st_other +// st_other values are stored in the second byte of get/setFlags +void MCELF::setOther(MCSymbolData &SD, unsigned Other) { + uint32_t OtherFlags = SD.getFlags() & ~(0x3f << ELF_Other_Shift); + SD.setFlags(OtherFlags | (Other << ELF_Other_Shift)); +} + +unsigned MCELF::getOther(MCSymbolData &SD) { + unsigned Other = + (SD.getFlags() & (0x3f << ELF_Other_Shift)) >> ELF_Other_Shift; + return Other; +} + } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 8ddbfbbe8a4..a9c35ccdf35 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -504,6 +504,10 @@ void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { llvm_unreachable("Generic ELF doesn't support this directive"); } +MCSymbolData &MCELFStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { + return getAssembler().getOrCreateSymbolData(*Symbol); +} + void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { llvm_unreachable("ELF doesn't support this directive"); } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 7d79d62830f..9857f7bb08d 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -620,3 +620,8 @@ void MCStreamer::Finish() { FinishImpl(); } + +MCSymbolData &MCStreamer::getOrCreateSymbolData(MCSymbol *Symbol) { + report_fatal_error("Not supported!"); + return *(static_cast (NULL)); +} -- 2.34.1