Skip to content

Commit dbef6ee

Browse files
committed
Add DWARF source line debug info
1 parent 759f0eb commit dbef6ee

7 files changed

Lines changed: 392 additions & 7 deletions

File tree

binaryninjaapi.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19930,6 +19930,21 @@ namespace BinaryNinja {
1993019930
{}
1993119931
};
1993219932

19933+
/*!
19934+
\ingroup debuginfo
19935+
*/
19936+
struct DebugSourceLineInfo
19937+
{
19938+
std::string sourceFile;
19939+
uint64_t address;
19940+
uint32_t line;
19941+
uint32_t column;
19942+
19943+
DebugSourceLineInfo(std::string sourceFile, uint64_t address, uint32_t line, uint32_t column = 0) :
19944+
sourceFile(sourceFile), address(address), line(line), column(column)
19945+
{}
19946+
};
19947+
1993319948
/*!
1993419949
\ingroup debuginfo
1993519950
*/
@@ -19950,6 +19965,7 @@ namespace BinaryNinja {
1995019965
std::vector<NameAndType> GetTypes(const std::string& parserName = "") const;
1995119966
std::vector<DebugFunctionInfo> GetFunctions(const std::string& parserName = "") const;
1995219967
std::vector<DataVariableAndName> GetDataVariables(const std::string& parserName = "") const;
19968+
std::vector<DebugSourceLineInfo> GetSourceLines(const std::string& parserName = "") const;
1995319969

1995419970
Ref<Type> GetTypeByName(const std::string& parserName, const std::string& name) const;
1995519971
std::optional<std::tuple<uint64_t, Ref<Type>>> GetDataVariableByName(
@@ -19961,11 +19977,14 @@ namespace BinaryNinja {
1996119977
std::vector<std::tuple<std::string, uint64_t, Ref<Type>>> GetDataVariablesByName(const std::string& name) const;
1996219978
std::vector<std::tuple<std::string, std::string, Ref<Type>>> GetDataVariablesByAddress(
1996319979
const uint64_t address) const;
19980+
std::vector<std::tuple<std::string, DebugSourceLineInfo>> GetSourceLinesByAddress(
19981+
const uint64_t address) const;
1996419982

1996519983
bool RemoveParserInfo(const std::string& parserName);
1996619984
bool RemoveParserTypes(const std::string& parserName);
1996719985
bool RemoveParserFunctions(const std::string& parserName);
1996819986
bool RemoveParserDataVariables(const std::string& parserName);
19987+
bool RemoveParserSourceLines(const std::string& parserName);
1996919988

1997019989
bool RemoveTypeByName(const std::string& parserName, const std::string& name);
1997119990
bool RemoveFunctionByIndex(const std::string& parserName, const size_t index);
@@ -19974,6 +19993,7 @@ namespace BinaryNinja {
1997419993
bool AddType(const std::string& name, Ref<Type> type, const std::vector<std::string>& components = {});
1997519994
bool AddFunction(const DebugFunctionInfo& function);
1997619995
bool AddDataVariable(uint64_t address, Ref<Type> type, const std::string& name = "", const std::vector<std::string>& components = {});
19996+
bool AddSourceLine(const DebugSourceLineInfo& lineInfo);
1997719997
};
1997819998

1997919999
/*!

binaryninjacore.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -861,10 +861,10 @@ extern "C"
861861
RelativeToBinaryStartDisassemblyAddressMode,
862862
RelativeToSegmentStartDisassemblyAddressMode,
863863
RelativeToSectionStartDisassemblyAddressMode,
864-
RelativeToFunctionStartDisassemblyAddressMode,
865-
RelativeToAddressBaseOffsetDisassemblyAddressMode,
866-
RelativeToDataStartDisassemblyAddressMode,
867-
DisassemblyAddressModeMask = 0xFFFF,
864+
RelativeToFunctionStartDisassemblyAddressMode,
865+
RelativeToAddressBaseOffsetDisassemblyAddressMode,
866+
RelativeToDataStartDisassemblyAddressMode,
867+
DisassemblyAddressModeMask = 0xFFFF,
868868

869869
IncludeNameDisassemblyAddressModeFlag = 0x10000,
870870
DecimalDisassemblyAddressModeFlag = 0x20000,
@@ -3557,6 +3557,14 @@ extern "C"
35573557
size_t localVariableN;
35583558
} BNDebugFunctionInfo;
35593559

3560+
typedef struct BNDebugSourceLineInfo
3561+
{
3562+
char* sourceFile;
3563+
uint64_t address;
3564+
uint32_t line;
3565+
uint32_t column;
3566+
} BNDebugSourceLineInfo;
3567+
35603568
typedef struct BNSecretsProviderCallbacks
35613569
{
35623570
void* context;
@@ -8360,6 +8368,8 @@ extern "C"
83608368
BINARYNINJACOREAPI bool BNRemoveDebugParserFunctions(BNDebugInfo* const debugInfo, const char* const parserName);
83618369
BINARYNINJACOREAPI bool BNRemoveDebugParserDataVariables(
83628370
BNDebugInfo* const debugInfo, const char* const parserName);
8371+
BINARYNINJACOREAPI bool BNRemoveDebugParserSourceLines(
8372+
BNDebugInfo* const debugInfo, const char* const parserName);
83638373
BINARYNINJACOREAPI bool BNAddDebugType(
83648374
BNDebugInfo* const debugInfo, const char* const name, const BNType* const type, const char** const components, size_t components_count);
83658375
BINARYNINJACOREAPI BNNameAndType* BNGetDebugTypes(
@@ -8377,6 +8387,12 @@ extern "C"
83778387
BINARYNINJACOREAPI bool BNRemoveDebugFunctionByIndex(
83788388
BNDebugInfo* const debugInfo, const char* const parserName, const size_t index);
83798389
BINARYNINJACOREAPI void BNFreeDebugFunctions(BNDebugFunctionInfo* functions, size_t count);
8390+
BINARYNINJACOREAPI bool BNAddDebugSourceLine(BNDebugInfo* const debugInfo, BNDebugSourceLineInfo* lineInfo);
8391+
BINARYNINJACOREAPI BNDebugSourceLineInfo* BNGetDebugSourceLines(
8392+
BNDebugInfo* const debugInfo, const char* const name, size_t* count);
8393+
BINARYNINJACOREAPI BNDebugSourceLineInfo* BNGetDebugSourceLinesByAddress(
8394+
BNDebugInfo* const debugInfo, uint64_t address, size_t* count);
8395+
BINARYNINJACOREAPI void BNFreeDebugSourceLines(BNDebugSourceLineInfo* sourceLines, size_t count);
83808396
BINARYNINJACOREAPI bool BNAddDebugDataVariable(
83818397
BNDebugInfo* const debugInfo, uint64_t address, const BNType* const type, const char* name, const char** const components, size_t components_count);
83828398
BINARYNINJACOREAPI bool BNAddDebugDataVariableInfo(

debuginfo.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,27 @@ vector<DataVariableAndName> DebugInfo::GetDataVariables(const string& parserName
150150
return result;
151151
}
152152

153+
vector<DebugSourceLineInfo> DebugInfo::GetSourceLines(const string& parserName) const
154+
{
155+
size_t count;
156+
BNDebugSourceLineInfo* sourceLines =
157+
BNGetDebugSourceLines(m_object, parserName.size() == 0 ? nullptr : parserName.c_str(), &count);
158+
159+
if (sourceLines == nullptr)
160+
return {};
161+
162+
vector<DebugSourceLineInfo> result;
163+
result.reserve(count);
164+
for (size_t i = 0; i < count; ++i)
165+
{
166+
result.emplace_back(sourceLines[i].sourceFile ? sourceLines[i].sourceFile : "",
167+
sourceLines[i].address, sourceLines[i].line, sourceLines[i].column);
168+
}
169+
170+
BNFreeDebugSourceLines(sourceLines, count);
171+
return result;
172+
}
173+
153174

154175
// May return nullptr
155176
Ref<Type> DebugInfo::GetTypeByName(const string& parserName, const string& name) const
@@ -250,6 +271,28 @@ vector<tuple<string, string, Ref<Type>>> DebugInfo::GetDataVariablesByAddress(co
250271
return result;
251272
}
252273

274+
vector<tuple<string, DebugSourceLineInfo>> DebugInfo::GetSourceLinesByAddress(const uint64_t address) const
275+
{
276+
size_t count;
277+
BNDebugSourceLineInfo* sourceLines = BNGetDebugSourceLinesByAddress(m_object, address, &count);
278+
279+
if (sourceLines == nullptr)
280+
return {};
281+
282+
vector<tuple<string, DebugSourceLineInfo>> result;
283+
result.reserve(count);
284+
for (size_t i = 0; i < count; ++i)
285+
{
286+
// Parser names are not currently returned by this C API. Preserve the tuple shape for future
287+
// consistency with other debug-info lookup helpers.
288+
result.emplace_back("", DebugSourceLineInfo(sourceLines[i].sourceFile ? sourceLines[i].sourceFile : "",
289+
sourceLines[i].address, sourceLines[i].line, sourceLines[i].column));
290+
}
291+
292+
BNFreeDebugSourceLines(sourceLines, count);
293+
return result;
294+
}
295+
253296

254297
bool DebugInfo::RemoveParserInfo(const string& parserName)
255298
{
@@ -274,6 +317,11 @@ bool DebugInfo::RemoveParserDataVariables(const string& parserName)
274317
return BNRemoveDebugParserDataVariables(m_object, parserName.c_str());
275318
}
276319

320+
bool DebugInfo::RemoveParserSourceLines(const string& parserName)
321+
{
322+
return BNRemoveDebugParserSourceLines(m_object, parserName.c_str());
323+
}
324+
277325

278326
bool DebugInfo::RemoveTypeByName(const string& parserName, const string& name)
279327
{
@@ -355,6 +403,19 @@ bool DebugInfo::AddDataVariable(uint64_t address, Ref<Type> type, const string&
355403
return BNAddDebugDataVariable(m_object, address, type->GetObject(), name.c_str(), componentArray, components.size());
356404
}
357405

406+
bool DebugInfo::AddSourceLine(const DebugSourceLineInfo& lineInfo)
407+
{
408+
BNDebugSourceLineInfo input;
409+
input.sourceFile = lineInfo.sourceFile.size() ? BNAllocString(lineInfo.sourceFile.c_str()) : nullptr;
410+
input.address = lineInfo.address;
411+
input.line = lineInfo.line;
412+
input.column = lineInfo.column;
413+
414+
bool result = BNAddDebugSourceLine(m_object, &input);
415+
BNFreeString(input.sourceFile);
416+
return result;
417+
}
418+
358419

359420
/////////////////////
360421
// DebugInfoParser //

plugins/dwarf/dwarf_import/src/dwarfdebuginfo.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020

2121
use binaryninja::{
2222
binary_view::{BinaryView, BinaryViewBase},
23-
debuginfo::{DebugFunctionInfo, DebugInfo},
23+
debuginfo::{DebugFunctionInfo, DebugInfo, DebugSourceLineInfo},
2424
platform::Platform,
2525
rc::*,
2626
symbol::SymbolType,
@@ -54,6 +54,14 @@ pub(crate) struct FunctionInfoBuilder {
5454
pub(crate) frame_base: Option<FrameBase>,
5555
}
5656

57+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
58+
pub(crate) struct SourceLineInfoBuilder {
59+
pub(crate) source_file: String,
60+
pub(crate) address: u64,
61+
pub(crate) line: u32,
62+
pub(crate) column: u32,
63+
}
64+
5765
impl FunctionInfoBuilder {
5866
pub(crate) fn update(
5967
&mut self,
@@ -217,6 +225,7 @@ pub(crate) struct DebugInfoBuilder {
217225
full_function_name_indices: HashMap<String, usize>,
218226
types: IndexMap<TypeUID, DebugType>,
219227
data_variables: HashMap<u64, (Option<String>, TypeUID)>,
228+
source_lines: Vec<SourceLineInfoBuilder>,
220229
range_data_offsets: iset::IntervalMap<u64, i64>,
221230
}
222231

@@ -228,6 +237,7 @@ impl DebugInfoBuilder {
228237
full_function_name_indices: HashMap::new(),
229238
types: IndexMap::new(),
230239
data_variables: HashMap::new(),
240+
source_lines: vec![],
231241
range_data_offsets: iset::IntervalMap::new(),
232242
}
233243
}
@@ -358,6 +368,21 @@ impl DebugInfoBuilder {
358368
&self.functions
359369
}
360370

371+
pub(crate) fn insert_source_line(
372+
&mut self,
373+
source_file: String,
374+
address: u64,
375+
line: u32,
376+
column: u32,
377+
) {
378+
self.source_lines.push(SourceLineInfoBuilder {
379+
source_file,
380+
address,
381+
line,
382+
column,
383+
});
384+
}
385+
361386
#[allow(dead_code)]
362387
pub(crate) fn types(&self) -> Values<'_, TypeUID, DebugType> {
363388
self.types.values()
@@ -706,6 +731,17 @@ impl DebugInfoBuilder {
706731
}
707732
}
708733

734+
fn commit_source_lines(&self, debug_info: &mut DebugInfo) {
735+
for source_line in &self.source_lines {
736+
debug_info.add_source_line(&DebugSourceLineInfo::new(
737+
source_line.source_file.clone(),
738+
source_line.address,
739+
source_line.line,
740+
source_line.column,
741+
));
742+
}
743+
}
744+
709745
pub(crate) fn post_process(&mut self, bv: &BinaryView, _debug_info: &mut DebugInfo) -> &Self {
710746
// When originally resolving names, we need to check:
711747
// If there's already a name from binja that's "more correct" than what we found (has more namespaces)
@@ -762,12 +798,20 @@ impl DebugInfoBuilder {
762798
}
763799
}
764800

801+
let (diff, overflowed) = bv.start().overflowing_sub(bv.original_image_base());
802+
if !overflowed {
803+
for source_line in &mut self.source_lines {
804+
source_line.address = source_line.address.overflowing_add(diff).0;
805+
}
806+
}
807+
765808
self
766809
}
767810

768811
pub(crate) fn commit_info(&self, debug_info: &mut DebugInfo) {
769812
self.commit_types(debug_info);
770813
self.commit_data_variables(debug_info);
771814
self.commit_functions(debug_info);
815+
self.commit_source_lines(debug_info);
772816
}
773817
}

0 commit comments

Comments
 (0)