Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
18 changes: 18 additions & 0 deletions lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1118,3 +1118,21 @@ size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
}
return 0;
}

llvm::StringRef lldb_private::npdb::StripCDeclPrefix(llvm::StringRef mangled) {
// See
// https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC
if (!mangled.starts_with('_'))
return mangled;

// make sure this isn't __stdcall (`_{name}@{sizeof(params)}`) or __vectorcall
// (`{name}@@{sizeof(params)}`).
size_t last_at_pos = mangled.find_last_of('@');
if (last_at_pos != llvm::StringRef::npos &&
last_at_pos < mangled.size() - 1 &&
llvm::all_of(mangled.slice(last_at_pos + 1, mangled.size()),
llvm::isDigit))
return mangled;

return mangled.drop_front();
}
12 changes: 12 additions & 0 deletions lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ PdbTypeSymId GetBestPossibleDecl(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);

size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);

/// Strips the leading underscore of mangled __cdecl functions.
///
/// If the name comes from another calling convention, it is returned as-is.
///
/// \pre \c mangled must not be from a 64-bit environment as __cdecl names
/// aren't mangled there.
///
/// \param[in] mangled A mangled symbol name
/// \returns The stripped name if this name is a mangled __cdecl one. Otherwise,
/// the input is returned.
llvm::StringRef StripCDeclPrefix(llvm::StringRef mangled);

} // namespace npdb
} // namespace lldb_private

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2677,6 +2677,7 @@ SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) {

ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));

return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset));
}

Expand All @@ -2686,7 +2687,21 @@ SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so) {
so.segment, so.offset);
if (!symbol)
return std::nullopt;
return symbol->first.Name;

llvm::StringRef name = symbol->first.Name;
// "In non-64 bit environments" (on x86 in pactice), __cdecl functions get
// prefixed with an underscore. For compilers using LLVM, this happens in LLVM
// (as opposed to the compiler frontend). Because of this, DWARF doesn't
// contain the "full" mangled name in DW_AT_linkage_name for these functions.
// We strip the mangling here for compatibility with DWARF. See
// llvm.org/pr161676 and
// https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC
if ((symbol->first.Flags & PublicSymFlags::Function) !=
PublicSymFlags::None &&
m_index->dbi().getMachineType() == PDB_Machine::x86)
name = StripCDeclPrefix(name);

return name;
}

void SymbolFileNativePDB::CacheUdtDeclarations() {
Expand Down
51 changes: 51 additions & 0 deletions lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// clang-format off
// REQUIRES: lld, x86

// RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%t-32.exe %s
// RUN: lldb-test symbols %t-32.exe | FileCheck --check-prefixes CHECK-32,CHECK-BOTH %s
// RUN: %build --compiler=clang-cl --arch=64 --nodefaultlib --output=%t-64.exe %s
// RUN: lldb-test symbols %t-64.exe | FileCheck --check-prefixes CHECK-64,CHECK-BOTH %s

extern "C" {
int FuncCCall() { return 0; }
int __stdcall FuncStdCall() { return 0; }
int __fastcall FuncFastCall() { return 0; }
int __vectorcall FuncVectorCall() { return 0; }

int __cdecl _underscoreCdecl() { return 0; }
int __stdcall _underscoreStdcall() { return 0; }
int __fastcall _underscoreFastcall() { return 0; }
int __vectorcall _underscoreVectorcall() { return 0; }
}

int main() {
FuncCCall();
FuncStdCall();
FuncFastCall();
FuncVectorCall();
_underscoreCdecl();
_underscoreStdcall();
_underscoreFastcall();
_underscoreVectorcall();
return 0;
}

// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncCCall,
// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncVectorCall@@0,
// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreCdecl,
// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreVectorcall@@0,
// CHECK-BOTH-DAG: Function{{.*}}, demangled = main,

// __stdcall and __fastcall aren't available on 64 bit

// CHECK-32-DAG: Function{{.*}}, demangled = _FuncStdCall@0,
// CHECK-64-DAG: Function{{.*}}, demangled = FuncStdCall,

// CHECK-32-DAG: Function{{.*}}, demangled = @FuncFastCall@0,
// CHECK-64-DAG: Function{{.*}}, demangled = FuncFastCall,

// CHECK-32-DAG: Function{{.*}}, demangled = __underscoreStdcall@0,
// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreStdcall,

// CHECK-32-DAG: Function{{.*}}, demangled = @_underscoreFastcall@0,
// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreFastcall,
1 change: 1 addition & 0 deletions lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_lldb_unittest(SymbolFileNativePDBTests
PdbFPOProgramToDWARFExpressionTests.cpp
PdbUtilTests.cpp
UdtRecordCompleterTests.cpp

LINK_COMPONENTS
Expand Down
47 changes: 47 additions & 0 deletions lldb/unittests/SymbolFile/NativePDB/PdbUtilTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/NativePDB/PdbUtil.h"
#include "gtest/gtest.h"

using namespace lldb_private::npdb;

TEST(PdbUtil, StripCDeclPrefix) {
ASSERT_EQ(StripCDeclPrefix("main"), "main");

// __cdecl
ASSERT_EQ(StripCDeclPrefix("_main"), "main");
ASSERT_EQ(StripCDeclPrefix("__main"), "_main");
ASSERT_EQ(StripCDeclPrefix("_main@"), "main@");
ASSERT_EQ(StripCDeclPrefix("_main@foo"), "main@foo");
ASSERT_EQ(StripCDeclPrefix("_main@4@foo"), "main@4@foo");

// __stdcall
ASSERT_EQ(StripCDeclPrefix("_main@4"), "_main@4");
ASSERT_EQ(StripCDeclPrefix("_main@foo@4"), "_main@foo@4");
ASSERT_EQ(StripCDeclPrefix("_main@4@5"), "_main@4@5");

// __fastcall
ASSERT_EQ(StripCDeclPrefix("@main@4"), "@main@4");

// __vectorcall
ASSERT_EQ(StripCDeclPrefix("main@@4"), "main@@4");
ASSERT_EQ(StripCDeclPrefix("_main@@4"), "_main@@4");

// MS C++ mangling
ASSERT_EQ(StripCDeclPrefix("?a@@YAHD@Z"), "?a@@YAHD@Z");
// Itanium mangling (e.g. on MinGW)
ASSERT_EQ(StripCDeclPrefix("__Z7recursei"), "_Z7recursei");

ASSERT_EQ(StripCDeclPrefix("_"), "");
ASSERT_EQ(StripCDeclPrefix("_@"), "@");
ASSERT_EQ(StripCDeclPrefix(""), "");
ASSERT_EQ(StripCDeclPrefix("_@4"), "_@4");
ASSERT_EQ(StripCDeclPrefix("@4"), "@4");
ASSERT_EQ(StripCDeclPrefix("@"), "@");
}
Loading