Skip to content

Commit 52a8e1f

Browse files
Stylie777MaskRay
authored andcommitted
[AArch64][LLD] Parse Shared Files Program Headers for GCS GNU Attribute
To enable the checking of the GNU GCS Attributes when linking together an application, LLD needs to be able to parse a Shared Files program headers. This will enable a new option, allowing the user to output diagnostic information relating to if there are shared files being used that do not support the GCS extension. To define if a shared file support GCS, the GNU GCS Attribute will be stored within the Program Header, so this is parsed and, if found, the `andFeatures` value updated to reflect the support level.
1 parent c767b38 commit 52a8e1f

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

lld/ELF/InputFiles.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
#include "Target.h"
1919
#include "lld/Common/CommonLinkerContext.h"
2020
#include "lld/Common/DWARF.h"
21+
#include "llvm/ADT/ArrayRef.h"
2122
#include "llvm/ADT/CachedHashString.h"
2223
#include "llvm/ADT/STLExtras.h"
24+
#include "llvm/BinaryFormat/ELF.h"
2325
#include "llvm/LTO/LTO.h"
2426
#include "llvm/Object/IRObjectFile.h"
2527
#include "llvm/Support/ARMAttributeParser.h"
@@ -502,6 +504,7 @@ void ELFFileBase::init() {
502504
template <class ELFT> void ELFFileBase::init(InputFile::Kind k) {
503505
using Elf_Shdr = typename ELFT::Shdr;
504506
using Elf_Sym = typename ELFT::Sym;
507+
using Elf_Phdr = typename ELFT::Phdr;
505508

506509
// Initialize trivial attributes.
507510
const ELFFile<ELFT> &obj = getObj<ELFT>();
@@ -513,6 +516,10 @@ template <class ELFT> void ELFFileBase::init(InputFile::Kind k) {
513516
elfShdrs = sections.data();
514517
numELFShdrs = sections.size();
515518

519+
ArrayRef<Elf_Phdr> pHeaders = CHECK2(obj.program_headers(), this);
520+
elfPhdrs = pHeaders.data();
521+
numElfPhdrs = pHeaders.size();
522+
516523
// Find a symbol table.
517524
const Elf_Shdr *symtabSec =
518525
findSection(sections, k == SharedKind ? SHT_DYNSYM : SHT_SYMTAB);
@@ -1418,6 +1425,21 @@ std::vector<uint32_t> SharedFile::parseVerneed(const ELFFile<ELFT> &obj,
14181425
return verneeds;
14191426
}
14201427

1428+
// To determine if a shared file can support the AArch64 GCS extension, the program headers for the object
1429+
// need to be read. This ensures when input options are read, appropriate warning/error messages can be
1430+
// emitted depending on the user's command line options.
1431+
template <typename ELFT>
1432+
uint64_t SharedFile::parseGnuAttributes(const typename ELFT::PhdrRange headers) {
1433+
if(numElfPhdrs == 0)
1434+
return 0;
1435+
uint64_t attributes = 0;
1436+
for (unsigned i = 0; i < numElfPhdrs; i++)
1437+
if(headers[i].p_type == PT_GNU_PROPERTY && headers[i].p_flags & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
1438+
attributes |= GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
1439+
1440+
return attributes;
1441+
}
1442+
14211443
// We do not usually care about alignments of data in shared object
14221444
// files because the loader takes care of it. However, if we promote a
14231445
// DSO symbol to point to .bss due to copy relocation, we need to keep
@@ -1528,6 +1550,7 @@ template <class ELFT> void SharedFile::parse() {
15281550

15291551
verdefs = parseVerdefs<ELFT>(obj.base(), verdefSec);
15301552
std::vector<uint32_t> verneeds = parseVerneed<ELFT>(obj, verneedSec);
1553+
this->andFeatures = parseGnuAttributes<ELFT>(getELFPhdrs<ELFT>());
15311554

15321555
// Parse ".gnu.version" section which is a parallel array for the symbol
15331556
// table. If a given file doesn't have a ".gnu.version" section, we use

lld/ELF/InputFiles.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ class ELFFileBase : public InputFile {
206206
return typename ELFT::ShdrRange(
207207
reinterpret_cast<const typename ELFT::Shdr *>(elfShdrs), numELFShdrs);
208208
}
209+
template <typename ELFT> typename ELFT::PhdrRange getELFPhdrs() const {
210+
return typename ELFT::PhdrRange(
211+
reinterpret_cast<const typename ELFT::Phdr *>(elfPhdrs), numElfPhdrs);
212+
}
209213
template <typename ELFT> typename ELFT::SymRange getELFSyms() const {
210214
return typename ELFT::SymRange(
211215
reinterpret_cast<const typename ELFT::Sym *>(elfSyms), numSymbols);
@@ -224,8 +228,10 @@ class ELFFileBase : public InputFile {
224228
StringRef stringTable;
225229
const void *elfShdrs = nullptr;
226230
const void *elfSyms = nullptr;
231+
const void *elfPhdrs = nullptr;
227232
uint32_t numELFShdrs = 0;
228233
uint32_t firstGlobal = 0;
234+
uint32_t numElfPhdrs = 0;
229235

230236
// Below are ObjFile specific members.
231237

@@ -364,6 +370,8 @@ class SharedFile : public ELFFileBase {
364370
template <typename ELFT>
365371
std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj,
366372
const typename ELFT::Shdr *sec);
373+
template <typename ELFT>
374+
uint64_t parseGnuAttributes(const typename ELFT::PhdrRange headers);
367375
};
368376

369377
class BinaryFile : public InputFile {

0 commit comments

Comments
 (0)