Skip to content

Commit 77c230f

Browse files
committed
[GOFF] Add writing of section symbols
The GOFF format uses symbol definitions to represent sections and symbols. Introducing a section can require up to 3 symbol definitions. However, most of these details are not needed by the AsmPrinter. To mapped from a section (a MCSectionGOFF) to the symbol definitions, a new class called MCGOFFSymbolMapper is used. The same information can also be used by the assembly output, which justifies this centralized approach. Writing the mapped symbols is then straight forward.
1 parent 7810f30 commit 77c230f

File tree

8 files changed

+765
-39
lines changed

8 files changed

+765
-39
lines changed

llvm/include/llvm/BinaryFormat/GOFF.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,91 @@ enum SubsectionKind : uint8_t {
169169
SK_PPA1 = 2,
170170
SK_PPA2 = 4,
171171
};
172+
173+
// The standard System/390 convention is to name the high-order (leftmost) bit
174+
// in a byte as bit zero. The Flags type helps to set bits in byte according
175+
// to this numeration order.
176+
class Flags {
177+
uint8_t Val;
178+
179+
constexpr static uint8_t bits(uint8_t BitIndex, uint8_t Length, uint8_t Value,
180+
uint8_t OldValue) {
181+
uint8_t Pos = 8 - BitIndex - Length;
182+
uint8_t Mask = ((1 << Length) - 1) << Pos;
183+
Value = Value << Pos;
184+
return (OldValue & ~Mask) | Value;
185+
}
186+
187+
public:
188+
constexpr Flags() : Val(0) {}
189+
constexpr Flags(uint8_t BitIndex, uint8_t Length, uint8_t Value)
190+
: Val(bits(BitIndex, Length, Value, 0)) {}
191+
192+
template <typename T>
193+
constexpr void set(uint8_t BitIndex, uint8_t Length, T NewValue) {
194+
Val = bits(BitIndex, Length, static_cast<uint8_t>(NewValue), Val);
195+
}
196+
197+
template <typename T>
198+
constexpr T get(uint8_t BitIndex, uint8_t Length) const {
199+
return static_cast<T>((Val >> (8 - BitIndex - Length)) &
200+
((1 << Length) - 1));
201+
}
202+
203+
constexpr operator uint8_t() const { return Val; }
204+
};
205+
206+
// Structure for the flag field of a symbol. See
207+
// https://www.ibm.com/docs/en/zos/3.1.0?topic=formats-external-symbol-definition-record,
208+
// offset 41, for the definition.
209+
struct SymbolFlags {
210+
Flags SymFlags;
211+
212+
#define GOFF_SYMBOL_FLAG(NAME, TYPE, BITINDEX, LENGTH) \
213+
void set##NAME(TYPE Val) { SymFlags.set<TYPE>(BITINDEX, LENGTH, Val); } \
214+
TYPE get##NAME() const { return SymFlags.get<TYPE>(BITINDEX, LENGTH); }
215+
216+
GOFF_SYMBOL_FLAG(FillBytePresence, bool, 0, 1)
217+
GOFF_SYMBOL_FLAG(Mangled, bool, 1, 1)
218+
GOFF_SYMBOL_FLAG(Renameable, bool, 2, 1)
219+
GOFF_SYMBOL_FLAG(RemovableClass, bool, 3, 1)
220+
GOFF_SYMBOL_FLAG(ReservedQwords, ESDReserveQwords, 5, 3)
221+
222+
#undef GOFF_SYMBOL_FLAG
223+
224+
constexpr operator uint8_t() const { return static_cast<uint8_t>(SymFlags); }
225+
};
226+
227+
// Structure for the behavioral attributes. See
228+
// https://www.ibm.com/docs/en/zos/3.1.0?topic=record-external-symbol-definition-behavioral-attributes
229+
// for the definition.
230+
struct BehavioralAttributes {
231+
Flags Attr[10];
232+
233+
#define GOFF_BEHAVIORAL_ATTRIBUTE(NAME, TYPE, ATTRIDX, BITINDEX, LENGTH) \
234+
void set##NAME(TYPE Val) { Attr[ATTRIDX].set<TYPE>(BITINDEX, LENGTH, Val); } \
235+
TYPE get##NAME() const { return Attr[ATTRIDX].get<TYPE>(BITINDEX, LENGTH); }
236+
237+
GOFF_BEHAVIORAL_ATTRIBUTE(Amode, GOFF::ESDAmode, 0, 0, 8)
238+
GOFF_BEHAVIORAL_ATTRIBUTE(Rmode, GOFF::ESDRmode, 1, 0, 8)
239+
GOFF_BEHAVIORAL_ATTRIBUTE(TextStyle, GOFF::ESDTextStyle, 2, 0, 4)
240+
GOFF_BEHAVIORAL_ATTRIBUTE(BindingAlgorithm, GOFF::ESDBindingAlgorithm, 2, 4,
241+
4)
242+
GOFF_BEHAVIORAL_ATTRIBUTE(TaskingBehavior, GOFF::ESDTaskingBehavior, 3, 0, 3)
243+
GOFF_BEHAVIORAL_ATTRIBUTE(ReadOnly, bool, 3, 4, 1)
244+
GOFF_BEHAVIORAL_ATTRIBUTE(Executable, GOFF::ESDExecutable, 3, 5, 3)
245+
GOFF_BEHAVIORAL_ATTRIBUTE(DuplicateSymbolSeverity,
246+
GOFF::ESDDuplicateSymbolSeverity, 4, 2, 2)
247+
GOFF_BEHAVIORAL_ATTRIBUTE(BindingStrength, GOFF::ESDBindingStrength, 4, 4, 4)
248+
GOFF_BEHAVIORAL_ATTRIBUTE(LoadingBehavior, GOFF::ESDLoadingBehavior, 5, 0, 2)
249+
GOFF_BEHAVIORAL_ATTRIBUTE(COMMON, bool, 5, 2, 1)
250+
GOFF_BEHAVIORAL_ATTRIBUTE(IndirectReference, bool, 5, 3, 1)
251+
GOFF_BEHAVIORAL_ATTRIBUTE(BindingScope, GOFF::ESDBindingScope, 5, 4, 4)
252+
GOFF_BEHAVIORAL_ATTRIBUTE(LinkageType, GOFF::ESDLinkageType, 6, 2, 1)
253+
GOFF_BEHAVIORAL_ATTRIBUTE(Alignment, GOFF::ESDAlignment, 6, 3, 5)
254+
255+
#undef GOFF_BEHAVIORAL_ATTRIBUTE
256+
};
172257
} // end namespace GOFF
173258

174259
} // end namespace llvm
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//===- MCGOFFSymbolMapper.h - Maps MC section/symbol to GOFF symbols ------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Maps a section or a symbol to the GOFF symbols it is composed of, and their
10+
// attributes.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_MC_MCGOFFSYMBOLMAPPER_H
15+
#define LLVM_MC_MCGOFFSYMBOLMAPPER_H
16+
17+
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/BinaryFormat/GOFF.h"
19+
#include "llvm/Support/Alignment.h"
20+
#include <string>
21+
#include <utility>
22+
23+
namespace llvm {
24+
class MCAssembler;
25+
class MCContext;
26+
class MCSectionGOFF;
27+
28+
// An "External Symbol Definition" in the GOFF file has a type, and depending on
29+
// the type a different subset of the fields is used.
30+
//
31+
// Unlike other formats, a 2 dimensional structure is used to define the
32+
// location of data. For example, the equivalent of the ELF .text section is
33+
// made up of a Section Definition (SD) and a class (Element Definition; ED).
34+
// The name of the SD symbol depends on the application, while the class has the
35+
// predefined name C_CODE64.
36+
//
37+
// Data can be placed into this structure in 2 ways. First, the data (in a text
38+
// record) can be associated with an ED symbol. To refer to data, a Label
39+
// Definition (LD) is used to give an offset into the data a name. When binding,
40+
// the whole data is pulled into the resulting executable, and the addresses
41+
// given by the LD symbols are resolved.
42+
//
43+
// The alternative is to use a Part Defiition (PR). In this case, the data (in a
44+
// text record) is associated with the part. When binding, only the data of
45+
// referenced PRs is pulled into the resulting binary.
46+
//
47+
// Both approaches are used, which means that the equivalent of a section in ELF
48+
// results in 3 GOFF symbol, either SD/ED/LD or SD/ED/PR. Moreover, certain
49+
// sections are fine with just defining SD/ED symbols. The SymbolMapper takes
50+
// care of all those details.
51+
52+
// Attributes for SD symbols.
53+
struct SDAttr {
54+
GOFF::ESDTaskingBehavior TaskingBehavior = GOFF::ESD_TA_Unspecified;
55+
GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
56+
};
57+
58+
// Attributes for ED symbols.
59+
struct EDAttr {
60+
bool IsReadOnly = false;
61+
GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
62+
GOFF::ESDAmode Amode;
63+
GOFF::ESDRmode Rmode;
64+
GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
65+
GOFF::ESDTextStyle TextStyle = GOFF::ESD_TS_ByteOriented;
66+
GOFF::ESDBindingAlgorithm BindAlgorithm = GOFF::ESD_BA_Concatenate;
67+
GOFF::ESDLoadingBehavior LoadBehavior = GOFF::ESD_LB_Initial;
68+
GOFF::ESDReserveQwords ReservedQwords = GOFF::ESD_RQ_0;
69+
GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Doubleword;
70+
};
71+
72+
// Attributes for LD symbols.
73+
struct LDAttr {
74+
bool IsRenamable = false;
75+
GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
76+
GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
77+
GOFF::ESDBindingStrength BindingStrength = GOFF::ESD_BST_Strong;
78+
GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
79+
GOFF::ESDAmode Amode;
80+
GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
81+
};
82+
83+
// Attributes for PR symbols.
84+
struct PRAttr {
85+
bool IsRenamable = false;
86+
bool IsReadOnly = false; // ???? Not documented.
87+
GOFF::ESDExecutable Executable = GOFF::ESD_EXE_Unspecified;
88+
GOFF::ESDNameSpaceId NameSpace = GOFF::ESD_NS_NormalName;
89+
GOFF::ESDLinkageType Linkage = GOFF::ESD_LT_XPLink;
90+
GOFF::ESDAmode Amode;
91+
GOFF::ESDBindingScope BindingScope = GOFF::ESD_BSC_Unspecified;
92+
GOFF::ESDDuplicateSymbolSeverity DuplicateSymbolSeverity =
93+
GOFF::ESD_DSS_NoWarning;
94+
GOFF::ESDAlignment Alignment = GOFF::ESD_ALIGN_Byte;
95+
uint32_t SortKey = 0;
96+
};
97+
98+
struct GOFFSectionData {
99+
// Name and attributes of SD symbol.
100+
StringRef SDName;
101+
SDAttr SDAttributes;
102+
103+
// Name and attributes of ED symbol.
104+
StringRef EDName;
105+
EDAttr EDAttributes;
106+
107+
// Name and attributes of LD or PR symbol.
108+
StringRef LDorPRName;
109+
LDAttr LDAttributes;
110+
PRAttr PRAttributes;
111+
112+
// Indicates if there is a LD or PR symbol.
113+
enum { None, LD, PR } Tag;
114+
115+
// Indicates if the SD symbol is to root symbol (aka the Csect Code).
116+
bool IsSDRootSD;
117+
};
118+
119+
class GOFFSymbolMapper {
120+
MCContext &Ctx;
121+
122+
std::string RootSDName;
123+
SDAttr RootSDAttributes;
124+
125+
std::string ADALDName;
126+
127+
StringRef BaseName;
128+
129+
bool IsCsectCodeNameEmpty;
130+
bool Is64Bit;
131+
bool UsesXPLINK;
132+
133+
public:
134+
GOFFSymbolMapper(MCContext &Ctx);
135+
GOFFSymbolMapper(MCAssembler &Asm);
136+
137+
// Required order: .text first, then .ada.
138+
std::pair<GOFFSectionData, bool> getSection(const MCSectionGOFF &Section);
139+
140+
void setBaseName();
141+
void determineRootSD(StringRef CSectCodeName);
142+
llvm::StringRef getRootSDName() const;
143+
const SDAttr &getRootSD() const;
144+
};
145+
146+
} // namespace llvm
147+
148+
#endif

llvm/lib/MC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_llvm_component_library(LLVMMC
2626
MCExpr.cpp
2727
MCFragment.cpp
2828
MCGOFFStreamer.cpp
29+
MCGOFFSymbolMapper.cpp
2930
MCInst.cpp
3031
MCInstPrinter.cpp
3132
MCInstrAnalysis.cpp

0 commit comments

Comments
 (0)