* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2013, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "DwarfUtils.h"
#include <String.h>
#include "CompilationUnit.h"
#include "Dwarf.h"
#include "DwarfFile.h"
void
DwarfUtils::GetDIEName(const DebugInfoEntry* entry, BString& _name)
{
const char* name = entry->Name();
if (name == NULL) {
if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
entry = abstractOrigin;
name = entry->Name();
}
}
if (name == NULL) {
if (DebugInfoEntry* specification = entry->Specification()) {
entry = specification;
name = entry->Name();
}
}
_name = name;
}
void
DwarfUtils::GetDIETypeName(const DebugInfoEntry* entry, BString& _name,
const DebugInfoEntry* requestingEntry)
{
const DIEType* type = dynamic_cast<const DIEType*>(entry);
if (type == NULL)
return;
const DIEModifiedType* modifiedType = dynamic_cast<const DIEModifiedType*>(
type);
BString typeName;
BString modifier;
if (modifiedType != NULL) {
const DIEType* baseType = type;
while ((modifiedType = dynamic_cast<const DIEModifiedType*>(
baseType)) != NULL) {
switch (modifiedType->Tag()) {
case DW_TAG_pointer_type:
modifier.Prepend("*");
break;
case DW_TAG_reference_type:
modifier.Prepend("&");
break;
case DW_TAG_const_type:
modifier.Prepend(" const ");
break;
default:
break;
}
baseType = modifiedType->GetType();
}
type = baseType;
}
if (type == NULL)
typeName = "void";
else
GetFullyQualifiedDIEName(type, typeName, requestingEntry);
if (modifier.Length() > 0) {
if (modifier[modifier.Length() - 1] == ' ')
modifier.Truncate(modifier.Length() - 1);
if (modifier[0] == ' ') {
typeName.Prepend("const ");
modifier.Remove(0, 7);
}
typeName += modifier;
}
_name = typeName;
}
void
DwarfUtils::GetFullDIEName(const DebugInfoEntry* entry, BString& _name)
{
BString generatedName;
const char* name = entry->Name();
if (name == NULL) {
if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
entry = abstractOrigin;
name = entry->Name();
}
}
if (name == NULL) {
if (DebugInfoEntry* specification = entry->Specification()) {
entry = specification;
name = entry->Name();
}
}
if (name == NULL) {
if (dynamic_cast<const DIEModifiedType*>(entry) != NULL)
GetDIETypeName(entry, _name);
return;
}
generatedName = name;
const DIESubprogram* subProgram = dynamic_cast<const DIESubprogram*>(
entry);
if (subProgram != NULL) {
generatedName += "(";
BString parameters;
DebugInfoEntryList::ConstIterator iterator
= subProgram->Parameters().GetIterator();
bool firstParameter = true;
while (iterator.HasNext()) {
DebugInfoEntry* parameterEntry = iterator.Next();
if (dynamic_cast<DIEUnspecifiedParameters*>(parameterEntry)
!= NULL) {
parameters += ", ...";
continue;
}
const DIEFormalParameter* parameter
= dynamic_cast<DIEFormalParameter*>(parameterEntry);
if (parameter == NULL) {
return;
}
if (parameter->IsArtificial())
continue;
BString paramName;
BString modifier;
DIEType* type = parameter->GetType();
GetDIETypeName(type, paramName, entry);
if (firstParameter)
firstParameter = false;
else
parameters += ", ";
parameters += paramName;
}
if (parameters.Length() > 0)
generatedName += parameters;
else
generatedName += "void";
generatedName += ")";
}
_name = generatedName;
}
void
DwarfUtils::GetFullyQualifiedDIEName(const DebugInfoEntry* entry,
BString& _name, const DebugInfoEntry* requestingEntry)
{
if (entry->Name() == NULL) {
if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin())
entry = abstractOrigin;
}
if (entry->Name() == NULL) {
if (DebugInfoEntry* specification = entry->Specification())
entry = specification;
}
_name.Truncate(0);
BString generatedName;
DebugInfoEntry* parent = entry->Parent();
while (parent != NULL) {
if (parent == requestingEntry)
break;
if (parent->IsNamespace()) {
BString parentName;
GetFullyQualifiedDIEName(parent, parentName);
if (parentName.Length() > 0) {
parentName += "::";
generatedName.Prepend(parentName);
}
break;
}
parent = parent->Parent();
}
BString name;
GetFullDIEName(entry, name);
if (name.Length() == 0)
return;
generatedName += name;
_name = generatedName;
}
bool
DwarfUtils::GetDeclarationLocation(DwarfFile* dwarfFile,
const DebugInfoEntry* entry, const char*& _directory, const char*& _file,
int32& _line, int32& _column)
{
uint32 file = 0;
uint32 line = 0;
uint32 column = 0;
bool fileSet = entry->GetDeclarationFile(file);
bool lineSet = entry->GetDeclarationLine(line);
bool columnSet = entry->GetDeclarationColumn(column);
if (!fileSet || !lineSet || !columnSet) {
if (DebugInfoEntry* abstractOrigin = entry->AbstractOrigin()) {
entry = abstractOrigin;
if (!fileSet)
fileSet = entry->GetDeclarationFile(file);
if (!lineSet)
lineSet = entry->GetDeclarationLine(line);
if (!columnSet)
columnSet = entry->GetDeclarationColumn(column);
}
}
if (!fileSet || !lineSet || !columnSet) {
if (DebugInfoEntry* specification = entry->Specification()) {
entry = specification;
if (!fileSet)
fileSet = entry->GetDeclarationFile(file);
if (!lineSet)
lineSet = entry->GetDeclarationLine(line);
if (!columnSet)
columnSet = entry->GetDeclarationColumn(column);
}
}
if (file == 0)
return false;
CompilationUnit* unit = dwarfFile->CompilationUnitForDIE(entry);
if (unit == NULL)
return false;
const char* directoryName;
const char* fileName = unit->FileAt(file - 1, &directoryName);
if (fileName == NULL)
return false;
_directory = directoryName;
_file = fileName;
_line = (int32)line - 1;
_column = (int32)column - 1;
return true;
}