diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-29 21:30:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-29 21:30:27 +0000 |
commit | 9e3ca9b3ba1e0fdf794978cb8c8ae386aad936ad (patch) | |
tree | 520d351b4ea72ceaff73c29410c126db55bdabef | |
parent | da06c7cfa0388de29a4024d8d386e48f2fb13ed6 (diff) |
Vendor import of lld release_50 branch r309439:vendor/lld/lld-release_50-r310316vendor/lld/lld-release_50-r309439
Notes
Notes:
svn path=/vendor/lld/dist/; revision=321698
svn path=/vendor/lld/lld-release_50-r310316/; revision=322266; tag=vendor/lld/lld-release_50-r310316
-rw-r--r-- | COFF/Config.h | 2 | ||||
-rw-r--r-- | COFF/Driver.cpp | 26 | ||||
-rw-r--r-- | ELF/InputFiles.cpp | 3 | ||||
-rw-r--r-- | ELF/InputFiles.h | 2 | ||||
-rw-r--r-- | ELF/SymbolTable.cpp | 63 | ||||
-rw-r--r-- | docs/ReleaseNotes.rst | 163 | ||||
-rw-r--r-- | lib/ReaderWriter/MachO/ObjCPass.cpp | 8 | ||||
-rw-r--r-- | test/COFF/manifest.test | 9 | ||||
-rw-r--r-- | test/COFF/manifestinput.test | 9 | ||||
-rw-r--r-- | test/ELF/Inputs/symver-archive1.s | 6 | ||||
-rw-r--r-- | test/ELF/Inputs/symver-archive2.s | 1 | ||||
-rw-r--r-- | test/ELF/symver-archive.s | 15 |
12 files changed, 246 insertions, 61 deletions
diff --git a/COFF/Config.h b/COFF/Config.h index a58e7d5585f2..7f8259d016e1 100644 --- a/COFF/Config.h +++ b/COFF/Config.h @@ -130,7 +130,7 @@ struct Configuration { std::map<StringRef, uint32_t> Section; // Options for manifest files. - ManifestKind Manifest = SideBySide; + ManifestKind Manifest = No; int ManifestID = 1; StringRef ManifestDependency; bool ManifestUAC = true; diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp index 35f4a04866c5..6df59e4b08df 100644 --- a/COFF/Driver.cpp +++ b/COFF/Driver.cpp @@ -899,18 +899,25 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { for (auto *Arg : Args.filtered(OPT_section)) parseSection(Arg->getValue()); - // Handle /manifest - if (auto *Arg = Args.getLastArg(OPT_manifest_colon)) - parseManifest(Arg->getValue()); + // Handle /manifestdependency. This enables /manifest unless /manifest:no is + // also passed. + if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) { + Config->ManifestDependency = Arg->getValue(); + Config->Manifest = Configuration::SideBySide; + } + + // Handle /manifest and /manifest: + if (auto *Arg = Args.getLastArg(OPT_manifest, OPT_manifest_colon)) { + if (Arg->getOption().getID() == OPT_manifest) + Config->Manifest = Configuration::SideBySide; + else + parseManifest(Arg->getValue()); + } // Handle /manifestuac if (auto *Arg = Args.getLastArg(OPT_manifestuac)) parseManifestUAC(Arg->getValue()); - // Handle /manifestdependency - if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) - Config->ManifestDependency = Arg->getValue(); - // Handle /manifestfile if (auto *Arg = Args.getLastArg(OPT_manifestfile)) Config->ManifestFile = Arg->getValue(); @@ -919,6 +926,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { for (auto *Arg : Args.filtered(OPT_manifestinput)) Config->ManifestInput.push_back(Arg->getValue()); + if (!Config->ManifestInput.empty() && + Config->Manifest != Configuration::Embed) { + fatal("/MANIFESTINPUT: requires /MANIFEST:EMBED"); + } + // Handle miscellaneous boolean flags. if (Args.hasArg(OPT_allowisolation_no)) Config->AllowIsolation = false; diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index d3c307d5cb6b..c609615fcc2e 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -91,8 +91,7 @@ template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() { template <class ELFT> Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S, uint64_t Offset) { - if (!DwarfLine) - initializeDwarfLine(); + llvm::call_once(InitDwarfLine, [this]() { initializeDwarfLine(); }); // The offset to CU is 0. const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0); diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index f6d3f907850c..006218b45d9e 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -24,6 +24,7 @@ #include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/Threading.h" #include <map> @@ -211,6 +212,7 @@ private: // single object file, so we cache debugging information in order to // parse it only once for each object file we link. std::unique_ptr<llvm::DWARFDebugLine> DwarfLine; + llvm::once_flag InitDwarfLine; }; // LazyObjectFile is analogous to ArchiveFile in the sense that diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index 83091057ebed..0c932400f0ad 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -211,6 +211,12 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { // Find an existing symbol or create and insert a new one. template <class ELFT> std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { + // <name>@@<version> means the symbol is the default version. In that + // case <name>@@<version> will be used to resolve references to <name>. + size_t Pos = Name.find("@@"); + if (Pos != StringRef::npos) + Name = Name.take_front(Pos); + auto P = Symtab.insert( {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)}); SymIndex &V = P.first->second; @@ -312,15 +318,36 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, return S; } +// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and +// foo@@VER. We want to effectively ignore foo, so give precedence to +// foo@@VER. +// FIXME: If users can transition to using +// .symver foo,foo@@@VER +// we can delete this hack. +static int compareVersion(Symbol *S, StringRef Name) { + if (Name.find("@@") != StringRef::npos && + S->body()->getName().find("@@") == StringRef::npos) + return 1; + if (Name.find("@@") == StringRef::npos && + S->body()->getName().find("@@") != StringRef::npos) + return -1; + return 0; +} + // We have a new defined symbol with the specified binding. Return 1 if the new // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are // strong defined symbols. -static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { +static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding, + StringRef Name) { if (WasInserted) return 1; SymbolBody *Body = S->body(); if (!Body->isInCurrentDSO()) return 1; + + if (int R = compareVersion(S, Name)) + return R; + if (Binding == STB_WEAK) return -1; if (S->isWeak()) @@ -333,8 +360,9 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { // is a conflict. If the new symbol wins, also update the binding. template <typename ELFT> static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding, - bool IsAbsolute, typename ELFT::uint Value) { - if (int Cmp = compareDefined(S, WasInserted, Binding)) { + bool IsAbsolute, typename ELFT::uint Value, + StringRef Name) { + if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) { if (Cmp > 0) S->Binding = Binding; return Cmp; @@ -362,7 +390,7 @@ Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); - int Cmp = compareDefined(S, WasInserted, Binding); + int Cmp = compareDefined(S, WasInserted, Binding, N); if (Cmp > 0) { S->Binding = Binding; replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); @@ -439,7 +467,7 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, - Section == nullptr, Value); + Section == nullptr, Value, Name); if (Cmp > 0) replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); @@ -485,7 +513,7 @@ Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding, std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, - /*IsAbs*/ false, /*Value*/ 0); + /*IsAbs*/ false, /*Value*/ 0, Name); if (Cmp > 0) replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0, nullptr, F); @@ -717,32 +745,9 @@ void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver, B->symbol()->VersionId = VersionId; } -static bool isDefaultVersion(SymbolBody *B) { - return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos; -} - // This function processes version scripts by updating VersionId // member of symbols. template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { - // Symbol themselves might know their versions because symbols - // can contain versions in the form of <name>@<version>. - // Let them parse and update their names to exclude version suffix. - for (Symbol *Sym : SymVector) { - SymbolBody *Body = Sym->body(); - bool IsDefault = isDefaultVersion(Body); - Body->parseSymbolVersion(); - - if (!IsDefault) - continue; - - // <name>@@<version> means the symbol is the default version. If that's the - // case, the symbol is not used only to resolve <name> of version <version> - // but also undefined unversioned symbols with name <name>. - SymbolBody *S = find(Body->getName()); - if (S && S->isUndefined()) - S->copy(Body); - } - // Handle edge cases first. handleAnonymousVersion(); diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 0d75311e4bce..fa6536ff46a8 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,5 +1,5 @@ ======================= -LLD 5.0.0 Release Notes +lld 5.0.0 Release Notes ======================= .. contents:: @@ -13,10 +13,16 @@ LLD 5.0.0 Release Notes Introduction ============ -This document contains the release notes for the LLD linker, release 5.0.0. -Here we describe the status of LLD, including major improvements -from the previous release. All LLD releases may be downloaded -from the `LLVM releases web site <http://llvm.org/releases/>`_. +lld is a linker from the LLVM project. It supports ELF (Unix), COFF (Windows) +and Mach-O (macOS), and it is generally faster than the GNU bfd or gold linkers +or the MSVC linker. + +lld is designed to be a drop-in replacement for the system linkers, so that +users don't need to change their build systems other than swapping the linker +command. + +All lld releases may be downloaded from the `LLVM releases web site +<http://llvm.org/releases/>`_. Non-comprehensive list of changes in this release ================================================= @@ -24,14 +30,153 @@ Non-comprehensive list of changes in this release ELF Improvements ---------------- -* Item 1. +* First and foremost, a lot of compatibility issues and bugs have been fixed. + Linker script support has significantly improved. As a result, we believe you + are very likely to be able to link your programs with lld without experiencing + any problem now. + +* Error message format has changed in order to improve readability. + Traditionally, linker's error messages are concise and arguably too terse. + This is an example of lld 4.0's error message (they are actually in one line):: + + /ssd/clang/bin/ld.lld: error: /ssd/llvm-project/lld/ELF/Writer.cpp:207: + undefined symbol 'lld::elf::EhFrameSection::addSection()' + + It is not easy to read because too much information is packed into a single line + and the embedded text, particularly a symbol name, is sometimes too long. + In lld 5.0, we use more vertical space to print out error messages in a more + structured manner like this:: + + bin/ld.lld: error: undefined symbol: lld::elf::EhFrameSection::addSection() + >>> Referenced by Writer.cpp:207 (/ssd/llvm-project/lld/ELF/Writer.cpp:207) + >>> Writer.cpp.o in archive lib/liblldELF.a + + As a bonus, the new error message contains source code location of the error + if it is available from debug info. + +* ``./configure`` scripts generated by GNU autoconf determines whether a linker + supports modern GNU-compatible features or not by searching for "GNU" in the + ``--help`` message. To be compatible with the scripts, we decided to add a + string "(compatible with GNU linkers)" to our ``--help`` message. This is a + hack, but just like the web browser's User-Agent string (which everyone still + claim they are "Mozilla/5.0"), we had no choice other than doing this to claim + that we accept GNU-compatible options. + +* The ``-Map`` option is added. The option is to make the linker to print out how + input files are mapped to the output file. Here is an example:: + + Address Size Align Out In Symbol + 00000000016d84d8 00000000008f8f50 8 .eh_frame + 00000000016d84d8 00000000008f8f50 8 <internal>:(.eh_frame) + 0000000001fd2000 00000000034b3bd0 16 .text + 0000000001fd2000 000000000000002a 1 /usr/lib/x86_64-linux-gnu/crt1.o:(.text) + 0000000001fd2000 0000000000000000 0 _start + 0000000001fd202a 0000000000000000 1 /usr/lib/x86_64-linux-gnu/crti.o:(.text) + 0000000001fd2030 00000000000000bd 16 /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o:(.text) + 0000000001fd2030 0000000000000000 0 deregister_tm_clones + 0000000001fd2060 0000000000000000 0 register_tm_clones + + This format is not the same as GNU linkers as our linker internal data + structure is different from them but contains the same amount of information + and should be more readable than their outputs. + + As with other lld features, the ``-Map`` option is designed with speed in mind. + The option would generate a hundred megabyte text file if you link a large + program with it. lld can usually do that in a few seconds, and it is generally + a few times faster than the GNU gold's ``-Map`` option. + +* lld's ``--gdb-index`` option used to be slow, but we sped it up so that it is + at least as fast as the GNU gold. + +* Some nonstandard relocations, such as R_X86_64_8 or R_X86_64_16, are supported. + They are not used for 32/64-bit applications, but some 16-bit bootloaders need + them. + +* Paddings in executable text sections are now filled with trap instructions + (such as INT3) instead of being left as null bytes. This change improves + disassembler outputs because it now prints out trap instructions instead of + trying to decode 0x00 as an instruction. It also makes debugging of some type + of program easier because when the control reaches a padding, the program + immediately raises an error. + +* The following options are added: ``-M``, ``-Map``, + ``-compress-debug-sections``, ``-emit-relocs``, + ``-error-unresolved-symbols``, ``-exclude-libs``, ``-filter``, + ``-no-dynamic-linker``, ``-no-export-dynamic``, ``-no-fatal-warnings``, + ``-print-map``, ``-warn-unresolved-symbols``, ``-z nocopyreloc``, + ``-z notext``, ``-z rodynamic`` + COFF Improvements ----------------- * Item 1. -MachO Improvements ------------------- +Contributors to lld 5.0 +======================= -* Item 1. +We had 63 individuals contribute to lld 5.0. Thank you so much! + +- Adrian McCarthy +- Alberto Magni +- Alexander Richardson +- Andre Vieira +- Andrew Ng +- Anton Korobeynikov +- Bob Haarman +- David Blaikie +- Davide Italiano +- David L. Jones +- Dmitry Mikulin +- Ed Maste +- Ed Schouten +- Eric Beckmann +- Eric Fiselier +- Eugene Leviant +- Evgeniy Stepanov +- Galina Kistanova +- George Rimar +- Hans Wennborg +- Igor Kudrin +- Ismail Donmez +- Jake Ehrlich +- James Henderson +- Joel Jones +- Jon Chesterfield +- Kamil Rytarowski +- Kevin Enderby +- Konstantin Zhuravlyov +- Kyungwoo Lee +- Leslie Zhai +- Mark Kettenis +- Martell Malone +- Martin Storsjo +- Meador Inge +- Mehdi Amini +- Michal Gorny +- NAKAMURA Takumi +- Paul Robinson +- Pavel Labath +- Petar Jovanovic +- Peter Collingbourne +- Peter Smith +- Petr Hosek +- Rafael Espindola +- Reid Kleckner +- Richard Smith +- Robert Clarke +- Rui Ueyama +- Saleem Abdulrasool +- Sam Clegg +- Sean Eveson +- Sean Silva +- Shankar Easwaran +- Shoaib Meenai +- Simon Atanasyan +- Simon Dardis +- Simon Tatham +- Sylvestre Ledru +- Tom Stellard +- Vitaly Buka +- Yuka Takahashi +- Zachary Turner diff --git a/lib/ReaderWriter/MachO/ObjCPass.cpp b/lib/ReaderWriter/MachO/ObjCPass.cpp index 4712d8ca969c..ccea081f053d 100644 --- a/lib/ReaderWriter/MachO/ObjCPass.cpp +++ b/lib/ReaderWriter/MachO/ObjCPass.cpp @@ -11,6 +11,7 @@ #include "ArchHandler.h" #include "File.h" +#include "MachONormalizedFileBinaryUtils.h" #include "MachOPasses.h" #include "lld/Core/DefinedAtom.h" #include "lld/Core/File.h" @@ -29,7 +30,7 @@ namespace mach_o { /// class ObjCImageInfoAtom : public SimpleDefinedAtom { public: - ObjCImageInfoAtom(const File &file, + ObjCImageInfoAtom(const File &file, bool isBig, MachOLinkingContext::ObjCConstraint objCConstraint, uint32_t swiftVersion) : SimpleDefinedAtom(file) { @@ -54,6 +55,8 @@ public: } Data.info.flags |= (swiftVersion << 8); + + normalized::write32(Data.bytes + 4, Data.info.flags, isBig); } ~ObjCImageInfoAtom() override = default; @@ -109,7 +112,8 @@ public: private: const DefinedAtom* getImageInfo() { - return new (_file.allocator()) ObjCImageInfoAtom(_file, + bool IsBig = MachOLinkingContext::isBigEndian(_ctx.arch()); + return new (_file.allocator()) ObjCImageInfoAtom(_file, IsBig, _ctx.objcConstraint(), _ctx.swiftVersion()); } diff --git a/test/COFF/manifest.test b/test/COFF/manifest.test index 33e80e75a4d5..accec48d6866 100644 --- a/test/COFF/manifest.test +++ b/test/COFF/manifest.test @@ -1,6 +1,10 @@ # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj +# RUN: rm -f %t.exe.manifest # RUN: lld-link /out:%t.exe /entry:main %t.obj +# RUN: test ! -e %t.exe.manifest + +# RUN: lld-link /manifest /out:%t.exe /entry:main %t.obj # RUN: FileCheck -check-prefix=MANIFEST %s < %t.exe.manifest MANIFEST: <?xml version="1.0" standalone="yes"?> @@ -15,7 +19,7 @@ MANIFEST: </security> MANIFEST: </trustInfo> MANIFEST: </assembly> -# RUN: lld-link /out:%t.exe /entry:main \ +# RUN: lld-link /out:%t.exe /entry:main /manifest \ # RUN: /manifestuac:"level='requireAdministrator' uiAccess='true'" %t.obj # RUN: FileCheck -check-prefix=UAC %s < %t.exe.manifest @@ -31,6 +35,7 @@ UAC: </security> UAC: </trustInfo> UAC: </assembly> +# /manifestdependency implies /manifest. (/manifestuac doesn't.) # RUN: lld-link /out:%t.exe /entry:main \ # RUN: /manifestdependency:"foo='bar'" %t.obj # RUN: FileCheck -check-prefix=DEPENDENCY %s < %t.exe.manifest @@ -52,7 +57,7 @@ DEPENDENCY: </dependentAssembly> DEPENDENCY: </dependency> DEPENDENCY: </assembly> -# RUN: lld-link /out:%t.exe /entry:main /manifestuac:no %t.obj +# RUN: lld-link /manifest /out:%t.exe /entry:main /manifestuac:no %t.obj # RUN: FileCheck -check-prefix=NOUAC %s < %t.exe.manifest NOUAC: <?xml version="1.0" standalone="yes"?> diff --git a/test/COFF/manifestinput.test b/test/COFF/manifestinput.test index 4eb1730bb0e4..95ebc22f7410 100644 --- a/test/COFF/manifestinput.test +++ b/test/COFF/manifestinput.test @@ -2,15 +2,6 @@ # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj # RUN: lld-link /out:%t.exe /entry:main \ -# RUN: /manifestuac:"level='requireAdministrator'" \ -# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj -# RUN: FileCheck %s < %t.exe.manifest - -CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly> - -# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj -# RUN: lld-link /out:%t.exe /entry:main \ # RUN: /manifest:embed \ # RUN: /manifestuac:"level='requireAdministrator'" \ # RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj diff --git a/test/ELF/Inputs/symver-archive1.s b/test/ELF/Inputs/symver-archive1.s new file mode 100644 index 000000000000..be7c64494215 --- /dev/null +++ b/test/ELF/Inputs/symver-archive1.s @@ -0,0 +1,6 @@ +.text +.globl x +.type x, @function +x: + +.symver x, xx@@VER diff --git a/test/ELF/Inputs/symver-archive2.s b/test/ELF/Inputs/symver-archive2.s new file mode 100644 index 000000000000..a9b9d0b0a35b --- /dev/null +++ b/test/ELF/Inputs/symver-archive2.s @@ -0,0 +1 @@ +call xx@PLT diff --git a/test/ELF/symver-archive.s b/test/ELF/symver-archive.s new file mode 100644 index 000000000000..be50503a3f5d --- /dev/null +++ b/test/ELF/symver-archive.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1 +# RUN: rm -f %t.a +# RUN: llvm-ar rcs %t.a %t1 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive1.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive2.s -o %t3.o +# RUN: ld.lld -o %t.out %t2.o %t3.o %t.a + +.text +.globl x +.type x, @function +x: + +.globl xx +xx = x |