Merge "bp2build: cc_library converter for //bionic/libdl:libdl_android"
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 5a73666..e90d019 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -69,6 +69,10 @@
// Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)
+ // GetPrebuiltCcStaticLibraryFiles returns paths to prebuilt cc static libraries, and whether the
+ // results were available
+ GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool)
+
// ** End cquery methods
// Issues commands to Bazel to receive results for all cquery requests
@@ -126,6 +130,11 @@
return result, result, ok
}
+func (m MockBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) {
+ result, ok := m.AllFiles[label]
+ return result, ok
+}
+
func (m MockBazelContext) InvokeBazel() error {
panic("unimplemented")
}
@@ -169,6 +178,19 @@
return outputFiles, ccObjects, ok
}
+// GetPrebuiltCcStaticLibraryFiles returns a slice of prebuilt static libraries for the given
+// label/archType if there are query results; otherwise, it enqueues the query and returns false.
+func (bazelCtx *bazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) {
+ result, ok := bazelCtx.cquery(label, cquery.GetPrebuiltCcStaticLibraryFiles, archType)
+ if !ok {
+ return nil, false
+ }
+
+ bazelOutput := strings.TrimSpace(result)
+ ret := cquery.GetPrebuiltCcStaticLibraryFiles.ParseResult(bazelOutput)
+ return ret, ok
+}
+
func (n noopBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
panic("unimplemented")
}
@@ -177,6 +199,10 @@
panic("unimplemented")
}
+func (n noopBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) {
+ panic("unimplemented")
+}
+
func (n noopBazelContext) InvokeBazel() error {
panic("unimplemented")
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 4a64c51..b88da2f 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -5,8 +5,9 @@
)
var (
- GetOutputFiles = &getOutputFilesRequestType{}
- GetOutputFilesAndCcObjectFiles = &getOutputFilesAndCcObjectFilesType{}
+ GetOutputFiles = &getOutputFilesRequestType{}
+ GetOutputFilesAndCcObjectFiles = &getOutputFilesAndCcObjectFilesType{}
+ GetPrebuiltCcStaticLibraryFiles = &getPrebuiltCcStaticLibraryFiles{}
)
type GetOutputFilesAndCcObjectFiles_Result struct {
@@ -86,6 +87,34 @@
return GetOutputFilesAndCcObjectFiles_Result{outputFiles, ccObjects}
}
+type getPrebuiltCcStaticLibraryFiles struct{}
+
+// Name returns the name of the starlark function to get prebuilt cc static library files
+func (g getPrebuiltCcStaticLibraryFiles) Name() string {
+ return "getPrebuiltCcStaticLibraryFiles"
+}
+
+// StarlarkFunctionBody returns the unindented body of a starlark function for extracting the static
+// library paths from a cc_import module.
+func (g getPrebuiltCcStaticLibraryFiles) StarlarkFunctionBody() string {
+ return `
+linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
+
+static_libraries = []
+for linker_input in linker_inputs:
+ for library in linker_input.libraries:
+ static_libraries.append(library.static_library.path)
+
+return ', '.join(static_libraries)`
+}
+
+// ParseResult returns a slice of bazel output paths to static libraries if any exist for the given
+// rawString corresponding to the string output which was created by evaluating the
+// StarlarkFunctionBody.
+func (g getPrebuiltCcStaticLibraryFiles) ParseResult(rawString string) []string {
+ return strings.Split(rawString, ", ")
+}
+
// splitOrEmpty is a modification of strings.Split() that returns an empty list
// if the given string is empty.
func splitOrEmpty(s string, sep string) []string {
diff --git a/cc/builder.go b/cc/builder.go
index 8c9743f..da8501c 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -132,7 +132,7 @@
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- Command: "CROSS_COMPILE=$crossCompile XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
+ Command: "XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
CommandDeps: []string{"$stripPath", "$xzCmd"},
Pool: darwinStripPool,
},
diff --git a/cc/cc.go b/cc/cc.go
index 1ce83a9..9176bc3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -56,8 +56,8 @@
ctx.TopDown("asan_deps", sanitizerDepsMutator(Asan))
ctx.BottomUp("asan", sanitizerMutator(Asan)).Parallel()
- ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
- ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
+ ctx.TopDown("hwasan_deps", sanitizerDepsMutator(Hwasan))
+ ctx.BottomUp("hwasan", sanitizerMutator(Hwasan)).Parallel()
ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(Fuzzer))
ctx.BottomUp("fuzzer", sanitizerMutator(Fuzzer)).Parallel()
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 6b9a3d5..3829b1e 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -305,6 +305,7 @@
func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewPrebuiltLibrary(hod)
library.BuildOnlyStatic()
+ module.bazelHandler = &prebuiltStaticLibraryBazelHandler{module: module, library: library}
return module, library
}
@@ -319,6 +320,52 @@
properties prebuiltObjectProperties
}
+type prebuiltStaticLibraryBazelHandler struct {
+ bazelHandler
+
+ module *Module
+ library *libraryDecorator
+}
+
+func (h *prebuiltStaticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ staticLibs, ok := bazelCtx.GetPrebuiltCcStaticLibraryFiles(label, ctx.Arch().ArchType)
+ if !ok {
+ return false
+ }
+ if len(staticLibs) > 1 {
+ ctx.ModuleErrorf("expected 1 static library from bazel target %q, got %s", label, staticLibs)
+ return false
+ }
+
+ // TODO(b/184543518): cc_prebuilt_library_static may have properties for re-exporting flags
+
+ // TODO(eakammer):Add stub-related flags if this library is a stub library.
+ // h.library.exportVersioningMacroIfNeeded(ctx)
+
+ // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
+ // validation will fail. For now, set this to an empty list.
+ // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
+ h.library.collectedSnapshotHeaders = android.Paths{}
+
+ if len(staticLibs) == 0 {
+ h.module.outputFile = android.OptionalPath{}
+ return true
+ }
+
+ out := android.PathForBazelOut(ctx, staticLibs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(out).Build()
+ ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ StaticLibrary: out,
+
+ TransitiveStaticLibrariesForOrdering: depSet,
+ })
+
+ return true
+}
+
func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
return &p.Prebuilt
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 8f17e4e..397121e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -83,7 +83,7 @@
const (
Asan SanitizerType = iota + 1
- hwasan
+ Hwasan
tsan
intOverflow
cfi
@@ -97,7 +97,7 @@
switch t {
case Asan:
return "asan"
- case hwasan:
+ case Hwasan:
return "hwasan"
case tsan:
return "tsan"
@@ -121,7 +121,7 @@
switch t {
case Asan:
return "address"
- case hwasan:
+ case Hwasan:
return "hwaddress"
case memtag_heap:
return "memtag_heap"
@@ -144,7 +144,7 @@
switch t {
case Asan:
return true
- case hwasan:
+ case Hwasan:
return true
case tsan:
return true
@@ -163,7 +163,7 @@
// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
func (t SanitizerType) incompatibleWithCfi() bool {
- return t == Asan || t == Fuzzer || t == hwasan
+ return t == Asan || t == Fuzzer || t == Hwasan
}
type SanitizeUserProps struct {
@@ -745,7 +745,7 @@
switch t {
case Asan:
return sanitize.Properties.Sanitize.Address
- case hwasan:
+ case Hwasan:
return sanitize.Properties.Sanitize.Hwaddress
case tsan:
return sanitize.Properties.Sanitize.Thread
@@ -767,7 +767,7 @@
// isUnsanitizedVariant returns true if no sanitizers are enabled.
func (sanitize *sanitize) isUnsanitizedVariant() bool {
return !sanitize.isSanitizerEnabled(Asan) &&
- !sanitize.isSanitizerEnabled(hwasan) &&
+ !sanitize.isSanitizerEnabled(Hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
!sanitize.isSanitizerEnabled(cfi) &&
!sanitize.isSanitizerEnabled(scs) &&
@@ -778,7 +778,7 @@
// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
return !sanitize.isSanitizerEnabled(Asan) &&
- !sanitize.isSanitizerEnabled(hwasan) &&
+ !sanitize.isSanitizerEnabled(Hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
!sanitize.isSanitizerEnabled(Fuzzer)
}
@@ -787,7 +787,7 @@
switch t {
case Asan:
sanitize.Properties.Sanitize.Address = boolPtr(b)
- case hwasan:
+ case Hwasan:
sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
case tsan:
sanitize.Properties.Sanitize.Thread = boolPtr(b)
@@ -902,7 +902,7 @@
if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
!d.SanitizeNever() &&
!d.IsSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == hwasan || t == scs {
+ if t == cfi || t == Hwasan || t == scs {
if d.StaticallyLinked() && d.SanitizerSupported(t) {
// Rust does not support some of these sanitizers, so we need to check if it's
// supported before setting this true.
@@ -1286,7 +1286,7 @@
// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
// to Make, because the sanitized version has a different suffix in name.
// For other types of sanitizers, suppress the variation that is disabled.
- if t != cfi && t != scs && t != hwasan {
+ if t != cfi && t != scs && t != Hwasan {
if isSanitizerEnabled {
modules[0].(PlatformSanitizeable).SetPreventInstall()
modules[0].(PlatformSanitizeable).SetHideFromMake()
@@ -1300,7 +1300,7 @@
if c.StaticallyLinked() && c.ExportedToMake() {
if t == cfi {
cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
- } else if t == hwasan {
+ } else if t == Hwasan {
hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
}
}
@@ -1417,7 +1417,7 @@
func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
return config.Once(hwasanStaticLibsKey, func() interface{} {
- return newSanitizerStaticLibsMap(hwasan)
+ return newSanitizerStaticLibsMap(Hwasan)
}).(*sanitizerStaticLibsMap)
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 3d31be4..3437d77 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -196,7 +196,7 @@
if m.sanitize != nil {
// scs and hwasan export both sanitized and unsanitized variants for static and header
// Always use unsanitized variants of them.
- for _, t := range []SanitizerType{scs, hwasan} {
+ for _, t := range []SanitizerType{scs, Hwasan} {
if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
return false
}
diff --git a/rust/androidmk.go b/rust/androidmk.go
index b0e6967..dea32a3 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -70,6 +70,11 @@
// If the compiler is disabled, this is a SourceProvider.
mod.SubAndroidMk(&ret, mod.sourceProvider)
}
+
+ if mod.sanitize != nil {
+ mod.SubAndroidMk(&ret, mod.sanitize)
+ }
+
ret.SubName += mod.Properties.SubName
return []android.AndroidMkEntries{ret}
diff --git a/rust/config/global.go b/rust/config/global.go
index 9208ddb..18776ab 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.50.0"
+ RustDefaultVersion = "1.51.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2018"
Stdlibs = []string{
diff --git a/rust/config/lints.go b/rust/config/lints.go
index 7c05e4f..ef6b315 100644
--- a/rust/config/lints.go
+++ b/rust/config/lints.go
@@ -54,6 +54,7 @@
"-A clippy::type-complexity",
"-A clippy::unnecessary-wraps",
"-A clippy::unusual-byte-groupings",
+ "-A clippy::upper-case-acronyms",
}
// Rust lints for vendor code.
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 2498aa1..ae3eff0 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -23,11 +23,12 @@
)
type SanitizeProperties struct {
- // enable AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer
+ // enable AddressSanitizer, HWAddressSanitizer, and others.
Sanitize struct {
- Address *bool `android:"arch_variant"`
- Fuzzer *bool `android:"arch_variant"`
- Never *bool `android:"arch_variant"`
+ Address *bool `android:"arch_variant"`
+ Hwaddress *bool `android:"arch_variant"`
+ Fuzzer *bool `android:"arch_variant"`
+ Never *bool `android:"arch_variant"`
}
SanitizerEnabled bool `blueprint:"mutated"`
SanitizeDep bool `blueprint:"mutated"`
@@ -43,7 +44,6 @@
"-C llvm-args=-sanitizer-coverage-level=3",
"-C llvm-args=-sanitizer-coverage-trace-compares",
"-C llvm-args=-sanitizer-coverage-inline-8bit-counters",
- "-C llvm-args=-sanitizer-coverage-stack-depth",
"-C llvm-args=-sanitizer-coverage-trace-geps",
"-C llvm-args=-sanitizer-coverage-prune-blocks=0",
"-Z sanitizer=address",
@@ -57,6 +57,11 @@
"-Z sanitizer=address",
}
+var hwasanFlags = []string{
+ "-Z sanitizer=hwaddress",
+ "-C target-feature=+tagged-globals",
+}
+
func boolPtr(v bool) *bool {
if v {
return &v
@@ -83,6 +88,15 @@
if ctx.Os() == android.Android && Bool(s.Address) {
sanitize.Properties.SanitizerEnabled = true
}
+
+ // HWASan requires AArch64 hardware feature (top-byte-ignore).
+ if ctx.Arch().ArchType != android.Arm64 {
+ s.Hwaddress = nil
+ }
+
+ if ctx.Os() == android.Android && Bool(s.Hwaddress) {
+ sanitize.Properties.SanitizerEnabled = true
+ }
}
type sanitize struct {
@@ -99,6 +113,9 @@
if Bool(sanitize.Properties.Sanitize.Address) {
flags.RustFlags = append(flags.RustFlags, asanFlags...)
}
+ if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+ flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
+ }
return flags, deps
}
@@ -111,11 +128,38 @@
if !mod.Enabled() {
return
}
+
+ variations := mctx.Target().Variations()
+ var depTag blueprint.DependencyTag
+ var deps []string
+
if Bool(mod.sanitize.Properties.Sanitize.Fuzzer) || Bool(mod.sanitize.Properties.Sanitize.Address) {
- mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{
- {Mutator: "link", Variation: "shared"},
- }...), cc.SharedDepTag(), config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan"))
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "shared"})
+ depTag = cc.SharedDepTag()
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
+ } else if mod.IsSanitizerEnabled(cc.Hwasan) {
+ // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+ if binary, ok := mod.compiler.(*binaryDecorator); ok {
+ if Bool(binary.Properties.Static_executable) {
+ mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
+ }
+ }
+
+ if mod.StaticallyLinked() {
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "static"})
+ depTag = cc.StaticDepTag(false)
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan_static")}
+ } else {
+ variations = append(variations,
+ blueprint.Variation{Mutator: "link", Variation: "shared"})
+ depTag = cc.SharedDepTag()
+ deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
+ }
}
+
+ mctx.AddFarVariationDependencies(variations, depTag, deps...)
}
}
@@ -128,6 +172,9 @@
case cc.Asan:
sanitize.Properties.Sanitize.Address = boolPtr(b)
sanitizerSet = true
+ case cc.Hwasan:
+ sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
+ sanitizerSet = true
default:
panic(fmt.Errorf("setting unsupported sanitizerType %d", t))
}
@@ -169,11 +216,23 @@
return sanitize.Properties.Sanitize.Fuzzer
case cc.Asan:
return sanitize.Properties.Sanitize.Address
+ case cc.Hwasan:
+ return sanitize.Properties.Sanitize.Hwaddress
default:
return nil
}
}
+func (sanitize *sanitize) AndroidMk(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ // Add a suffix for hwasan rlib libraries to allow surfacing both the sanitized and
+ // non-sanitized variants to make without a name conflict.
+ if entries.Class == "RLIB_LIBRARIES" || entries.Class == "STATIC_LIBRARIES" {
+ if sanitize.isSanitizerEnabled(cc.Hwasan) {
+ entries.SubName += ".hwasan"
+ }
+ }
+}
+
func (mod *Module) SanitizerSupported(t cc.SanitizerType) bool {
if mod.Host() {
return false
@@ -183,6 +242,8 @@
return true
case cc.Asan:
return true
+ case cc.Hwasan:
+ return true
default:
return false
}
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 43e6cbf..e3e5273 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -18,7 +18,6 @@
# Inputs:
# Environment:
# CLANG_BIN: path to the clang bin directory
-# CROSS_COMPILE: prefix added to readelf, objcopy tools
# XZ: path to the xz binary
# Arguments:
# -i ${file}: input file (required)
@@ -69,7 +68,7 @@
KEEP_SYMBOLS="--strip-unneeded-symbol=* --keep-symbols="
KEEP_SYMBOLS+="${outfile}.symbolList"
- "${CROSS_COMPILE}objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
+ "${CLANG_BIN}/llvm-objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
}
do_strip_keep_mini_debug_info() {
@@ -78,18 +77,13 @@
"${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
if [ -z $fail ]; then
- # Current prebult llvm-objcopy does not support --only-keep-debug flag,
- # and cannot process object files that are produced with the flag. Use
- # GNU objcopy instead for now. (b/141010852)
- "${CROSS_COMPILE}objcopy" --only-keep-debug "${infile}" "${outfile}.debug"
+ "${CLANG_BIN}/llvm-objcopy" --only-keep-debug "${infile}" "${outfile}.debug"
"${CLANG_BIN}/llvm-nm" -D "${infile}" --format=posix --defined-only 2> /dev/null | awk '{ print $1 }' | sort >"${outfile}.dynsyms"
"${CLANG_BIN}/llvm-nm" "${infile}" --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t" || $2 == "D") print $1 }' | sort > "${outfile}.funcsyms"
comm -13 "${outfile}.dynsyms" "${outfile}.funcsyms" > "${outfile}.keep_symbols"
echo >> "${outfile}.keep_symbols" # Ensure that the keep_symbols file is not empty.
- "${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
- "${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --remove-section .rustc --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
- "${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
- "${XZ}" --block-size=64k --threads=0 "${outfile}.mini_debuginfo"
+ "${CLANG_BIN}/llvm-objcopy" -S --keep-section .debug_frame --keep-symbols="${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo"
+ "${XZ}" --keep --block-size=64k --threads=0 "${outfile}.mini_debuginfo"
"${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
@@ -196,7 +190,6 @@
cat <<EOF > "${depsfile}"
${outfile}: \
${infile} \
- ${CROSS_COMPILE}objcopy \
${CLANG_BIN}/llvm-nm \
${CLANG_BIN}/llvm-objcopy \
${CLANG_BIN}/llvm-readelf \