Skip to content

Commit 5f8e25e

Browse files
committed
Respond to review comments.
Summary of changes * GcsReportPolicy enum has been changed to a struct. This allows for the use of a `toString()` function so the values can be passed to existing error lamdba functions within the Driver.cpp file. * Removed uneeded additional includes * `getZGcsReport` now supports the parsing of both `-zgcs-report` and `-zgcs-report-dynamic`. The GNU inheritance rules are also included in this function. * `SharedFile::parseGnuAttributes` now correctly parses the `.note.gnu.properties` section for the GCS Attributes. * Release notes updated. * aarch64-feature-gcs.s updated to be more streamline as per review comments.
1 parent 9583f8c commit 5f8e25e

File tree

6 files changed

+124
-108
lines changed

6 files changed

+124
-108
lines changed

lld/ELF/Config.h

+20-3
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,24 @@ enum LtoKind : uint8_t {UnifiedThin, UnifiedRegular, Default};
137137
enum class GcsPolicy { Implicit, Never, Always };
138138

139139
// For -z gcs-report= and -zgcs-report-dynamic
140-
enum class GcsReportPolicy { None, Warning, Error };
140+
struct GcsReportPolicy {
141+
enum Options { None, Warning, Error, Unknown } value;
142+
GcsReportPolicy(GcsReportPolicy::Options valueInput) : value(valueInput) {};
143+
144+
StringRef toString() {
145+
StringRef ret;
146+
if (value == Warning)
147+
ret = "warning";
148+
else if (value == Error)
149+
ret = "error";
150+
else
151+
ret = "none";
152+
153+
return ret;
154+
}
155+
156+
GcsReportPolicy::Options getValue() { return value; }
157+
};
141158

142159
struct SymbolVersion {
143160
llvm::StringRef name;
@@ -396,8 +413,8 @@ struct Config {
396413
UnresolvedPolicy unresolvedSymbolsInShlib;
397414
Target2Policy target2;
398415
GcsPolicy zGcs;
399-
GcsReportPolicy zGcsReport;
400-
GcsReportPolicy zGcsReportDynamic;
416+
GcsReportPolicy zGcsReport = GcsReportPolicy::None;
417+
GcsReportPolicy zGcsReportDynamic = GcsReportPolicy::None;
401418
bool power10Stubs;
402419
ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
403420
BuildIdKind buildId = BuildIdKind::None;

lld/ELF/Driver.cpp

+24-64
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,11 @@
4949
#include "llvm/ADT/STLExtras.h"
5050
#include "llvm/ADT/SetVector.h"
5151
#include "llvm/ADT/StringExtras.h"
52-
#include "llvm/ADT/StringRef.h"
5352
#include "llvm/ADT/StringSwitch.h"
54-
#include "llvm/BinaryFormat/ELF.h"
5553
#include "llvm/Config/llvm-config.h"
5654
#include "llvm/LTO/LTO.h"
5755
#include "llvm/Object/Archive.h"
58-
#include "llvm/Object/ELFTypes.h"
5956
#include "llvm/Object/IRObjectFile.h"
60-
#include "llvm/Option/ArgList.h"
6157
#include "llvm/Remarks/HotnessThresholdParser.h"
6258
#include "llvm/Support/CommandLine.h"
6359
#include "llvm/Support/Compression.h"
@@ -72,7 +68,6 @@
7268
#include "llvm/Support/TimeProfiler.h"
7369
#include "llvm/Support/raw_ostream.h"
7470
#include <cstdlib>
75-
#include <memory>
7671
#include <tuple>
7772
#include <utility>
7873

@@ -405,9 +400,9 @@ static void checkOptions(Ctx &ctx) {
405400
ErrAlways(ctx) << "-z bti-report only supported on AArch64";
406401
if (ctx.arg.zPauthReport != "none")
407402
ErrAlways(ctx) << "-z pauth-report only supported on AArch64";
408-
if (ctx.arg.zGcsReport != GcsReportPolicy::None)
403+
if (ctx.arg.zGcsReport.getValue() != GcsReportPolicy::None)
409404
ErrAlways(ctx) << "-z gcs-report only supported on AArch64";
410-
if (ctx.arg.zGcsReportDynamic != GcsReportPolicy::None)
405+
if (ctx.arg.zGcsReportDynamic.getValue() != GcsReportPolicy::None)
411406
ErrAlways(ctx) << "-z gcs-report-dynamic only supported on AArch64";
412407
if (ctx.arg.zGcs != GcsPolicy::Implicit)
413408
ErrAlways(ctx) << "-z gcs only supported on AArch64";
@@ -581,54 +576,29 @@ static GcsPolicy getZGcs(Ctx &ctx, opt::InputArgList &args) {
581576
return ret;
582577
}
583578

584-
static GcsReportPolicy getZGcsReport(Ctx &ctx, opt::InputArgList &args) {
579+
static GcsReportPolicy
580+
getZGcsReport(Ctx &ctx, opt::InputArgList &args, bool isReportDynamic,
581+
GcsReportPolicy gcsReportValue = GcsReportPolicy::None) {
585582
GcsReportPolicy ret = GcsReportPolicy::None;
586583

587584
for (auto *arg : args.filtered(OPT_z)) {
588585
std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
589-
if (kv.first == "gcs-report") {
586+
if ((!isReportDynamic && kv.first == "gcs-report") ||
587+
(isReportDynamic && kv.first == "gcs-report-dynamic")) {
590588
arg->claim();
591-
if (kv.second == "none")
592-
ret = GcsReportPolicy::None;
593-
else if (kv.second == "warning")
594-
ret = GcsReportPolicy::Warning;
595-
else if (kv.second == "error")
596-
ret = GcsReportPolicy::Error;
597-
else
598-
ErrAlways(ctx) << "unknown -z gcs-report= value: " << kv.second;
589+
ret = StringSwitch<GcsReportPolicy>(kv.second)
590+
.Case("none", GcsReportPolicy::None)
591+
.Case("warning", GcsReportPolicy::Warning)
592+
.Case("error", GcsReportPolicy::Error)
593+
.Default(GcsReportPolicy::Unknown);
594+
if (ret.getValue() == GcsReportPolicy::Unknown)
595+
ErrAlways(ctx) << "unknown -z " << kv.first << "= value: " << kv.second;
599596
}
600597
}
601598

602-
return ret;
603-
}
604-
605-
static GcsReportPolicy getZGcsReportDynamic(Ctx &ctx, opt::InputArgList &args) {
606-
GcsReportPolicy ret = GcsReportPolicy::None;
607-
for (auto *arg : args.filtered(OPT_z)) {
608-
std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
609-
if (kv.first == "gcs-report-dynamic") {
610-
arg->claim();
611-
if (kv.second == "none")
612-
ret = GcsReportPolicy::None;
613-
else if (kv.second == "warning")
614-
ret = GcsReportPolicy::Warning;
615-
else if (kv.second == "error")
616-
ret = GcsReportPolicy::Error;
617-
else
618-
ErrAlways(ctx) << "unknown -z gcs-report-dynamic= value: " << kv.second;
619-
// once the gcs-report-dynamic option has been processed, we want to break
620-
// from the loop to ensure we do not overwrite the return value if the
621-
// user has also passed a value for the gcs-report option.
622-
break;
623-
}
624-
// If the user has not defined a value for gcs-report-dynamic, but has for
625-
// gcs-report, we want to inherit that value for gcs-report-dynamic. This is
626-
// capped at a warning to ensure a users module can still build, while
627-
// providing information relating to if a dynamic object supports GCS.
628-
if (kv.first == "gcs-report" &&
629-
(kv.second == "warning" || kv.second == "error"))
630-
ret = GcsReportPolicy::Warning;
631-
}
599+
if (isReportDynamic && gcsReportValue.getValue() != GcsReportPolicy::None &&
600+
ret.getValue() == GcsReportPolicy::None)
601+
ret = GcsReportPolicy::Warning;
632602

633603
return ret;
634604
}
@@ -1612,8 +1582,9 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
16121582
ctx.arg.zForceBti = hasZOption(args, "force-bti");
16131583
ctx.arg.zForceIbt = hasZOption(args, "force-ibt");
16141584
ctx.arg.zGcs = getZGcs(ctx, args);
1615-
ctx.arg.zGcsReport = getZGcsReport(ctx, args);
1616-
ctx.arg.zGcsReportDynamic = getZGcsReportDynamic(ctx, args);
1585+
ctx.arg.zGcsReport = getZGcsReport(ctx, args, false);
1586+
ctx.arg.zGcsReportDynamic =
1587+
getZGcsReport(ctx, args, true, ctx.arg.zGcsReport);
16171588
ctx.arg.zGlobal = hasZOption(args, "global");
16181589
ctx.arg.zGnustack = getZGnuStack(args);
16191590
ctx.arg.zHazardplt = hasZOption(args, "hazardplt");
@@ -2891,17 +2862,6 @@ static void readSecurityNotes(Ctx &ctx) {
28912862
return {ctx, DiagLevel::None};
28922863
return report(config);
28932864
};
2894-
auto reportGcsPolicy = [&](GcsReportPolicy config,
2895-
bool cond) -> ELFSyncStream {
2896-
if (cond)
2897-
return {ctx, DiagLevel::None};
2898-
StringRef configString = "none";
2899-
if (config == GcsReportPolicy::Warning)
2900-
configString = "warning";
2901-
else if (config == GcsReportPolicy::Error)
2902-
configString = "error";
2903-
return report(configString);
2904-
};
29052865
for (ELFFileBase *f : ctx.objectFiles) {
29062866
uint32_t features = f->andFeatures;
29072867

@@ -2911,8 +2871,8 @@ static void readSecurityNotes(Ctx &ctx) {
29112871
<< ": -z bti-report: file does not have "
29122872
"GNU_PROPERTY_AARCH64_FEATURE_1_BTI property";
29132873

2914-
reportGcsPolicy(ctx.arg.zGcsReport,
2915-
features & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
2874+
reportUnless(ctx.arg.zGcsReport.toString(),
2875+
features & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
29162876
<< f
29172877
<< ": -z gcs-report: file does not have "
29182878
"GNU_PROPERTY_AARCH64_FEATURE_1_GCS property";
@@ -2989,8 +2949,8 @@ static void readSecurityNotes(Ctx &ctx) {
29892949
// either `warning` or `error`.
29902950
if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
29912951
for (SharedFile *f : ctx.sharedFiles)
2992-
reportGcsPolicy(ctx.arg.zGcsReportDynamic,
2993-
f->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
2952+
reportUnless(ctx.arg.zGcsReportDynamic.toString(),
2953+
f->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
29942954
<< f
29952955
<< ": GCS is required by -z gcs, but this shared library lacks the "
29962956
"necessary property note. The "

lld/ELF/InputFiles.cpp

+63-18
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@
1818
#include "Target.h"
1919
#include "lld/Common/CommonLinkerContext.h"
2020
#include "lld/Common/DWARF.h"
21-
#include "llvm/ADT/ArrayRef.h"
2221
#include "llvm/ADT/CachedHashString.h"
2322
#include "llvm/ADT/STLExtras.h"
24-
#include "llvm/BinaryFormat/ELF.h"
2523
#include "llvm/LTO/LTO.h"
2624
#include "llvm/Object/IRObjectFile.h"
2725
#include "llvm/Support/ARMAttributeParser.h"
@@ -1425,22 +1423,65 @@ std::vector<uint32_t> SharedFile::parseVerneed(const ELFFile<ELFT> &obj,
14251423
return verneeds;
14261424
}
14271425

1428-
// To determine if a shared file can support the AArch64 GCS extension, the
1429-
// program headers for the object need to be read. This ensures when input
1430-
// options are read, appropriate warning/error messages can be emitted depending
1431-
// on the user's command line options.
1426+
// To determine if a shared file can support any of the GNU Attributes,
1427+
// the .note.gnu.properties section need to be read. This has to be done
1428+
// differently for SharedFiles as the information available is not as
1429+
// extensive as a normal object input file. This will take the program
1430+
// headers, along with the SHT_NOTE section header to find the relevant
1431+
// information. This uses a similar process to the readGnuProperty
1432+
// function, but designed specifically for SharedFiles.
14321433
template <typename ELFT>
1433-
uint64_t
1434-
SharedFile::parseGnuAttributes(const typename ELFT::PhdrRange headers) {
1435-
if (numElfPhdrs == 0)
1436-
return 0;
1437-
uint64_t attributes = 0;
1438-
for (unsigned i = 0; i < numElfPhdrs; i++)
1439-
if (headers[i].p_type == PT_GNU_PROPERTY &&
1440-
headers[i].p_flags & GNU_PROPERTY_AARCH64_FEATURE_1_GCS)
1441-
attributes |= GNU_PROPERTY_AARCH64_FEATURE_1_GCS;
1442-
1443-
return attributes;
1434+
void SharedFile::parseGnuAttributes(const uint8_t *base,
1435+
const typename ELFT::PhdrRange headers,
1436+
const typename ELFT::Shdr *sHeader) {
1437+
auto err = [&](const uint8_t *place) -> ELFSyncStream {
1438+
auto diag = Err(ctx);
1439+
diag << this->getName() << ":(" << ".note.gnu.properties" << "+0x"
1440+
<< Twine::utohexstr(place - base) << "): ";
1441+
return diag;
1442+
};
1443+
1444+
if (numElfPhdrs == 0 || sHeader == nullptr)
1445+
return;
1446+
uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
1447+
? GNU_PROPERTY_AARCH64_FEATURE_1_AND
1448+
: GNU_PROPERTY_X86_FEATURE_1_AND;
1449+
1450+
for (unsigned i = 0; i < numElfPhdrs; i++) {
1451+
if (headers[i].p_type != PT_GNU_PROPERTY)
1452+
continue;
1453+
1454+
const typename ELFT::Note note(
1455+
*reinterpret_cast<const typename ELFT::Nhdr *>(base +
1456+
headers[i].p_vaddr));
1457+
if (note.getType() != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU")
1458+
continue;
1459+
1460+
// Read a body of a NOTE record, which consists of type-length-value fields.
1461+
ArrayRef<uint8_t> desc = note.getDesc(sHeader->sh_addralign);
1462+
while (!desc.empty()) {
1463+
const uint8_t *place = desc.data();
1464+
if (desc.size() < 8)
1465+
return void(err(place) << "program property is too short");
1466+
uint32_t type = read32(ctx, desc.data());
1467+
uint32_t size = read32(ctx, desc.data() + 4);
1468+
desc = desc.slice(8);
1469+
if (desc.size() < size)
1470+
return void(err(place) << "program property is too short");
1471+
1472+
// We found a FEATURE_1_AND field. There may be more than one of these
1473+
// in a .note.gnu.property section, for a relocatable object we
1474+
// accumulate the bits set.
1475+
if (type == featureAndType) {
1476+
if (size < 4)
1477+
return void(err(place) << "FEATURE_1_AND entry is too short");
1478+
this->andFeatures |= read32(ctx, desc.data());
1479+
}
1480+
1481+
// Padding is present in the note descriptor, if necessary.
1482+
desc = desc.slice(alignTo<(ELFT::Is64Bits ? 8 : 4)>(size));
1483+
}
1484+
}
14441485
}
14451486

14461487
// We do not usually care about alignments of data in shared object
@@ -1487,6 +1528,7 @@ template <class ELFT> void SharedFile::parse() {
14871528
const Elf_Shdr *versymSec = nullptr;
14881529
const Elf_Shdr *verdefSec = nullptr;
14891530
const Elf_Shdr *verneedSec = nullptr;
1531+
const Elf_Shdr *noteSec = nullptr;
14901532
symbols = std::make_unique<Symbol *[]>(numSymbols);
14911533

14921534
// Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
@@ -1507,6 +1549,9 @@ template <class ELFT> void SharedFile::parse() {
15071549
case SHT_GNU_verneed:
15081550
verneedSec = &sec;
15091551
break;
1552+
case SHT_NOTE:
1553+
noteSec = &sec;
1554+
break;
15101555
}
15111556
}
15121557

@@ -1553,7 +1598,7 @@ template <class ELFT> void SharedFile::parse() {
15531598

15541599
verdefs = parseVerdefs<ELFT>(obj.base(), verdefSec);
15551600
std::vector<uint32_t> verneeds = parseVerneed<ELFT>(obj, verneedSec);
1556-
this->andFeatures = parseGnuAttributes<ELFT>(getELFPhdrs<ELFT>());
1601+
parseGnuAttributes<ELFT>(obj.base(), getELFPhdrs<ELFT>(), noteSec);
15571602

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

lld/ELF/InputFiles.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,9 @@ class SharedFile : public ELFFileBase {
371371
std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj,
372372
const typename ELFT::Shdr *sec);
373373
template <typename ELFT>
374-
uint64_t parseGnuAttributes(const typename ELFT::PhdrRange headers);
374+
void parseGnuAttributes(const uint8_t *base,
375+
const typename ELFT::PhdrRange headers,
376+
const typename ELFT::Shdr *sHeader);
375377
};
376378

377379
class BinaryFile : public InputFile {

lld/docs/ReleaseNotes.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ Non-comprehensive list of changes in this release
2525

2626
ELF Improvements
2727
----------------
28-
* For AArch64, support for the -zgcs-report-dynamic option has been added. This will provide users with
28+
* For AArch64, support for the `-zgcs-report-dynamic`` option has been added. This will provide users with
2929
the ability to check any Dynamic Objects explicitly passed to LLD for the GNU GCS Attribute Flag. This is
30-
required for all files when linking with GCS enabled. Unless defined by the user, -zgcs-report-dynamic
31-
inherits its value from the -zgcs-report option, capped at the `warning` level to ensure that a users
30+
required for all files when linking with GCS enabled. Unless defined by the user, `-zgcs-report-dynamic``
31+
inherits its value from the `-zgcs-report` option, capped at the `warning` level to ensure that a users
3232
module can still compile. This behaviour is designed to match the GNU ld Linker.
3333

3434
Breaking changes

lld/test/ELF/aarch64-feature-gcs.s

+11-19
Original file line numberDiff line numberDiff line change
@@ -51,34 +51,26 @@
5151

5252
## gcs-report-dynamic should report any dynamic objects that does not have the gcs property. This also ensures the inhertance from gcs-report is working correctly.
5353

54-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
55-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report-dynamic=warning -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
56-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
57-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report=error -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
58-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
59-
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report=error -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
60-
# RUN: not ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report-dynamic=error -z gcs-report=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-ERROR-DYNAMIC %s
61-
# RUN: not ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -o /dev/null -z gcs-report-dynamic=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-ERROR-DYNAMIC %s
54+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
55+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report-dynamic=warning -z gcs-report=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
56+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
57+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report=error -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
58+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
59+
# RUN: ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report=error -z gcs-report-dynamic=warning -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-WARN-DYNAMIC %s
60+
# RUN: not ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report-dynamic=error -z gcs-report=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-ERROR-DYNAMIC %s
61+
# RUN: not ld.lld func1-gcs.o func3-gcs.o no-gcs.so force-gcs.so -z gcs-report-dynamic=error -z gcs=always 2>&1 | FileCheck --check-prefix=REPORT-ERROR-DYNAMIC %s
6262

6363
# REPORT-WARN-DYNAMIC: warning: no-gcs.so: GCS is required by -z gcs, but this shared library lacks the necessary property note. The dynamic loader might not enable GCS or refuse to load the program unless all shared library dependancies have the GCS marking.
6464
# REPORT-WARN-DYNAMIC-NOT: warning: force-gcs.so: GCS is required by -z gcs, but this shared library lacks the necessary property note. The dynamic loader might not enable GCS or refuse to load the program unless all shared library dependancies have the GCS marking.
6565
# REPORT-ERROR-DYNAMIC: error: no-gcs.so: GCS is required by -z gcs, but this shared library lacks the necessary property note. The dynamic loader might not enable GCS or refuse to load the program unless all shared library dependancies have the GCS marking.
6666
# REPORT-ERROR-DYNAMIC-NOT: error: force-gcs.so: GCS is required by -z gcs, but this shared library lacks the necessary property note. The dynamic loader might not enable GCS or refuse to load the program unless all shared library dependancies have the GCS marking.
6767

6868
## An invalid gcs option should give an error
69-
# RUN: not ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs=nonsense 2>&1 | FileCheck --check-prefix=INVALID %s
69+
# RUN: not ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs=nonsense -z gcs-report=nonsense -z gcs-report-dynamic=nonsense 2>&1 | FileCheck --check-prefix=INVALID %s
7070

7171
# INVALID: error: unknown -z gcs= value: nonsense
72-
73-
## An invalid gcs option should give an error
74-
# RUN: not ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs-report=nonsense 2>&1 | FileCheck --check-prefix=INVALID-GCS-REPORT %s
75-
76-
# INVALID-GCS-REPORT: error: unknown -z gcs-report= value: nonsense
77-
78-
## An invalid gcs-report-dynamic option should give an error
79-
# RUN: not ld.lld func1-gcs.o func2-gcs.o func3-gcs.o -z gcs-report-dynamic=nonsense 2>&1 | FileCheck --check-prefix=INVALID-GCS-REPORT-DYNAMIC %s
80-
81-
# INVALID-GCS-REPORT-DYNAMIC: error: unknown -z gcs-report-dynamic= value: nonsense
72+
# INVALID: error: unknown -z gcs-report= value: nonsense
73+
# INVALID: error: unknown -z gcs-report-dynamic= value: nonsense
8274

8375
#--- func1-gcs.s
8476
.section ".note.gnu.property", "a"

0 commit comments

Comments
 (0)