Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lldb/source/API/SBDebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,9 @@ bool SBDebugger::GetDefaultArchitecture(char *arch_name, size_t arch_name_len) {
ArchSpec default_arch = Target::GetDefaultArchitecture();

if (default_arch.IsValid()) {
const std::string &triple_str = default_arch.GetTriple().str();
const llvm::StringRef triple_str = default_arch.GetTriple().str(4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to add a couple of methods to ArchSpec so that we have a single place that specifies how we format the triple.

class ArchSpec {
    ...
    static std::string GetTripleStr(const llvm::Triple &triple) {
        return triple.normalize(CanonicalForm::FOUR_IDENT);
    }
    
    std::string GetTripleStr() {
        return GetTripleStr(GetTriple());
    }
};

Then if we have an ArchSpec we can just call the GetTripleStr() function on it and if we just have the Triple we can still use the static version.

if (!triple_str.empty())
::snprintf(arch_name, arch_name_len, "%s", triple_str.c_str());
::snprintf(arch_name, arch_name_len, "%s", triple_str.str().c_str());
else
::snprintf(arch_name, arch_name_len, "%s",
default_arch.GetArchitectureName());
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/API/SBModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ const char *SBModule::GetTriple() {
if (!module_sp)
return nullptr;

std::string triple(module_sp->GetArchitecture().GetTriple().str());
std::string triple(module_sp->GetArchitecture().GetTriple().str(4));
// Unique the string so we don't run into ownership issues since the const
// strings put the string into the string pool once and the strings never
// comes out
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/API/SBModuleSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void SBModuleSpec::SetObjectName(const char *name) {
const char *SBModuleSpec::GetTriple() {
LLDB_INSTRUMENT_VA(this);

std::string triple(m_opaque_up->GetArchitecture().GetTriple().str());
std::string triple(m_opaque_up->GetArchitecture().GetTriple().str(4));
// Unique the string so we don't run into ownership issues since the const
// strings put the string into the string pool once and the strings never
// comes out
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/API/SBTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,7 @@ const char *SBTarget::GetTriple() {
LLDB_INSTRUMENT_VA(this);

if (TargetSP target_sp = GetSP()) {
std::string triple(target_sp->GetArchitecture().GetTriple().str());
std::string triple(target_sp->GetArchitecture().GetTriple().str(4));
// Unique the string so we don't run into ownership issues since the const
// strings put the string into the string pool once and the strings never
// comes out
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ bool Module::GetIsDynamicLinkEditor() {
uint32_t Module::Hash() {
std::string identifier;
llvm::raw_string_ostream id_strm(identifier);
id_strm << m_arch.GetTriple().str() << '-' << m_file.GetPath();
id_strm << m_arch.GetTriple().str(4) << '-' << m_file.GetPath();
if (m_object_name)
id_strm << '(' << m_object_name << ')';
if (m_object_offset > 0)
Expand All @@ -1626,7 +1626,7 @@ uint32_t Module::Hash() {
std::string Module::GetCacheKey() {
std::string key;
llvm::raw_string_ostream strm(key);
strm << m_arch.GetTriple().str() << '-' << m_file.GetFilename();
strm << m_arch.GetTriple().str(4) << '-' << m_file.GetFilename();
if (m_object_name)
strm << '(' << m_object_name << ')';
strm << '-' << llvm::format_hex(Hash(), 10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,11 +494,12 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
} else {
uuid_str = "and no LC_UUID found in load commands ";
}
LLDB_LOGF(
log,
"DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
"kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
LLDB_LOGF(log,
"DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
"kernel binary image found at 0x%" PRIx64
" with arch '%s' %s",
addr, kernel_arch.GetTriple().str(4).str().c_str(),
uuid_str.c_str());
}
return memory_module_sp->GetUUID();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ lldb_private::UUID DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress(
LLDB_LOGF(log,
"DynamicLoaderFreeBSDKernel::CheckForKernelImageAtAddress: "
"kernel binary image found at 0x%" PRIx64 " with arch '%s' %s",
addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str());
addr, kernel_arch.GetTriple().str(4).str().c_str(),
uuid_str.c_str());

return memory_module_sp->GetUUID();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ static void SetupTargetOpts(CompilerInstance &compiler,

const auto target_machine = target_arch.GetMachine();
if (target_arch.IsValid()) {
std::string triple = target_arch.GetTriple().str();
std::string triple(target_arch.GetTriple().str(4));
compiler.getTargetOpts().Triple = triple;
LLDB_LOGF(log, "Using %s as the target triple",
compiler.getTargetOpts().Triple.c_str());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ ClangModulesDeclVendor::Create(Target &target) {
"-fsyntax-only",
"-femit-all-decls",
"-target",
arch.GetTriple().str(),
arch.GetTriple().str(4).str(),
"-fmodules-validate-system-headers",
"-Werror=non-modular-include-in-framework-module",
"-Xclang=-fincremental-extensions",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) {
static llvm::SmallVector<std::string, 2>
getTargetIncludePaths(const llvm::Triple &triple) {
llvm::SmallVector<std::string, 2> paths;
if (!triple.str().empty()) {
paths.push_back("/usr/include/" + triple.str());
llvm::StringRef triple_no_objfmt = triple.str(4);
if (!triple_no_objfmt.empty()) {
paths.push_back(("/usr/include/" + triple_no_objfmt).str());
if (!triple.getArchName().empty() ||
triple.getOSAndEnvironmentName().empty())
paths.push_back(("/usr/include/" + triple.getArchName() + "-" +
Expand Down Expand Up @@ -75,13 +76,14 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f,
parent_path(posix_dir, Style::posix).ends_with("c++")) {
if (!m_std_inc.TrySet(posix_dir))
return false;
if (triple.str().empty())
llvm::StringRef triple_no_objfmt = triple.str(4);
if (triple_no_objfmt.empty())
return true;

posix_dir.consume_back("c++/v1");
// Check if this is a target-specific libc++ include directory.
return m_std_target_inc.TrySet(
(posix_dir + triple.str() + "/c++/v1").str());
(posix_dir + triple_no_objfmt + "/c++/v1").str());
}

std::optional<llvm::StringRef> inc_path;
Expand Down
6 changes: 4 additions & 2 deletions lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5148,6 +5148,7 @@ void ObjectFileMachO::GetAllArchSpecs(const llvm::MachO::mach_header &header,
llvm::Triple base_triple = base_arch.GetTriple();
base_triple.setOS(llvm::Triple::UnknownOS);
base_triple.setOSName(llvm::StringRef());
base_triple.setObjectFormat(llvm::Triple::MachO);

if (header.filetype == MH_PRELOAD) {
if (header.cputype == CPU_TYPE_ARM) {
Expand Down Expand Up @@ -6745,8 +6746,9 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
make_core = true;
break;
default:
error = Status::FromErrorStringWithFormat(
"unsupported core architecture: %s", target_triple.str().c_str());
error =
Status::FromErrorStringWithFormat("unsupported core architecture: %s",
target_triple.str(4).str().c_str());
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,13 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
m_gdb_client_up->SendEnvironment(launch_info.GetEnvironment());

ArchSpec arch_spec = launch_info.GetArchitecture();
const char *arch_triple = arch_spec.GetTriple().str().c_str();
const std::string arch_triple = arch_spec.GetTriple().str(4).str();

m_gdb_client_up->SendLaunchArchPacket(arch_triple);
m_gdb_client_up->SendLaunchArchPacket(arch_triple.c_str());
LLDB_LOGF(
log,
"PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'",
__FUNCTION__, arch_triple ? arch_triple : "<NULL>");
__FUNCTION__, !arch_triple.empty() ? arch_triple.c_str() : "<NULL>");

{
// Scope for the scoped timeout object
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,8 +497,8 @@ static void ParseLangArgs(LangOptions &Opts, ArchSpec arch) {
TypeSystemClang::TypeSystemClang(llvm::StringRef name,
llvm::Triple target_triple) {
m_display_name = name.str();
if (!target_triple.str().empty())
SetTargetTriple(target_triple.str());
if (!target_triple.str(4).empty())
SetTargetTriple(target_triple.str(4));
// The caller didn't pass an ASTContext so create a new one for this
// TypeSystemClang.
CreateASTContext();
Expand All @@ -509,7 +509,7 @@ TypeSystemClang::TypeSystemClang(llvm::StringRef name,
TypeSystemClang::TypeSystemClang(llvm::StringRef name,
ASTContext &existing_ctxt) {
m_display_name = name.str();
SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str());
SetTargetTriple(existing_ctxt.getTargetInfo().getTriple().str(4));

m_ast_up.reset(&existing_ctxt);
GetASTMap().Insert(&existing_ctxt, this);
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Target/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ void Platform::GetStatus(Stream &strm) {

ArchSpec arch(GetSystemArchitecture());
if (arch.IsValid()) {
if (!arch.GetTriple().str().empty()) {
if (!arch.GetTriple().str(4).empty()) {
strm.Printf(" Triple: ");
arch.DumpTriple(strm.AsRawOstream());
strm.EOL();
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Target/Statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(
module_stat.path.append(1, ')');
}
module_stat.uuid = module->GetUUID().GetAsString();
module_stat.triple = module->GetArchitecture().GetTriple().str();
module_stat.triple = module->GetArchitecture().GetTriple().str(4);
json_modules.emplace_back(module_stat.ToJSON());
}
}
Expand Down
116 changes: 116 additions & 0 deletions lldb/unittests/ObjectFile/MachO/TestObjectFileMachO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,120 @@ TEST_F(ObjectFileMachOTest, IndirectSymbolsInTheSharedCache) {
for (size_t i = 0; i < 10; i++)
OF->ParseSymtab(symtab);
}

TEST_F(ObjectFileMachOTest, ObjectFormatWithVersionLoadCommand) {
// A Mach-O file of arm64 CPU type and macOS 10.14.0
const char *yamldata = R"(
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x0100000C
cpusubtype: 0x00000000
filetype: 0x00000001
ncmds: 1
sizeofcmds: 176
flags: 0x00002000
reserved: 0x00000000
LoadCommands:
- cmd: LC_BUILD_VERSION
cmdsize: 24
platform: 1
minos: 658944
sdk: 658944
ntools: 0
- cmd: LC_SEGMENT_64
cmdsize: 152
segname: __TEXT
vmaddr: 0
vmsize: 4
fileoff: 208
filesize: 4
maxprot: 7
initprot: 7
nsects: 1
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000000000
content: 'AABBCCDD'
size: 4
offset: 208
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
...
)";

// Perform setup.
llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(file->moduleSpec());
ASSERT_NE(module_sp, nullptr);
auto object_file = module_sp->GetObjectFile();
ASSERT_NE(object_file, nullptr);

// Verify that the object file is recognized as Mach-O.
ASSERT_EQ(object_file->GetArchitecture().GetTriple().getObjectFormat(),
llvm::Triple::MachO);
}

TEST_F(ObjectFileMachOTest, ObjectFormatWithoutVersionLoadCommand) {
// A Mach-O file of arm64 CPU type, without load command LC_BUILD_VERSION.
const char *yamldata = R"(
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x0100000C
cpusubtype: 0x00000000
filetype: 0x00000001
ncmds: 1
sizeofcmds: 152
flags: 0x00002000
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 152
segname: __TEXT
vmaddr: 0
vmsize: 4
fileoff: 184
filesize: 4
maxprot: 7
initprot: 7
nsects: 1
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000000000000
content: 'AABBCCDD'
size: 4
offset: 184
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
...
)";

// Perform setup.
llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
auto module_sp = std::make_shared<Module>(file->moduleSpec());
ASSERT_NE(module_sp, nullptr);
auto object_file = module_sp->GetObjectFile();
ASSERT_NE(object_file, nullptr);

// Verify that the object file is recognized as Mach-O.
ASSERT_EQ(object_file->GetArchitecture().GetTriple().getObjectFormat(),
llvm::Triple::MachO);
}
#endif
21 changes: 21 additions & 0 deletions llvm/include/llvm/TargetParser/Triple.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,27 @@ class Triple {

const std::string &str() const { return Data; }

/// Return the triple string but only keep the first \p N components.
///
/// The returned string will preserve the first \p N components exactly the
/// same as the original (including the leading "-" and the value, empty or
/// not).
///
/// E.g. Triple("arm64-apple-ios").str(5) == "arm64-apple-ios"
/// E.g. Triple("arm64-apple-ios--").str(5) == "arm64-apple-ios--"
/// E.g. Triple("arm64-apple-ios--").str(4) == "arm64-apple-ios-"
/// E.g. Triple("arm64-apple-ios--").str(3) == "arm64-apple-ios"
/// E.g. Triple("arm64-apple-ios--").str(2) == "arm64-apple"
/// E.g. Triple("arm64-apple-ios--").str(1) == "arm64"
/// E.g. Triple("arm64-apple-ios--").str(0) == ""
///
/// This method does not normalize any triple strings. Clients that need to
/// handle the non-canonical triples that users often specify should use the
/// normalize method.
///
/// \returns the (shorterned) triple string.
StringRef str(size_t N) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we already have this capability in the normalize method

std::string normalize(CanonicalForm Form = CanonicalForm::ANY) const {

For the use cases in this PR we could do triple.normalize(CanonicalForm::FOUR_IDENT)

Copy link
Contributor Author

@royitaqi royitaqi Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between this new method str(N) and normalize() is that the former won't canonicalize the triple string and the latter will.

From method doc of normalize():

In particular, it handles the common case in which otherwise valid components are in the wrong order.

So I think str(N) can be seen as an alternative to normalize() where the triple string isn't canonicalized.

The use cases in this PR doesn't call normalize(), so I assume the triple string/order of components should be preserved. Admittedly, I haven't checked if they have been normalized already.

Copy link
Contributor Author

@royitaqi royitaqi Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the use cases in this PR we could do triple.normalize(CanonicalForm::FOUR_IDENT)

@clayborg / @jasonmolenda: Do you see a downside of what @dmpots suggested? @dmpots had a good point in offline discussion that these are for display in LLDB, so it maybe preferred that they are normalized. I agree with that, but I'm just not sure if that will change thing that you guys end up not like (similar to how I initially made the objfmt component to show up in the triple string).


const std::string &getTriple() const { return Data; }

/// Whether the triple is empty / default constructed.
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/TargetParser/Triple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,30 @@ std::string Triple::merge(const Triple &Other) const {
return Other.str();
}

StringRef Triple::str(size_t N) const {
// If empty, return empty
if (N == 0 || Data == "")
return "";

// If keeping all components, return a full clone
if (N >= 5)
return Data;

// Find the N-th separator (which is after the N'th component)
size_t p = StringRef::npos;
for (uint32_t i = 0; i < N; ++i) {
p = Data.find('-', p + 1);
if (p == StringRef::npos)
break;
}

// Create a triple
if (p == StringRef::npos)
return Data;
else
return StringRef(Data).substr(0, p);
}

bool Triple::isMacOSXVersionLT(unsigned Major, unsigned Minor,
unsigned Micro) const {
assert(isMacOSX() && "Not an OS X triple!");
Expand Down
Loading