* Extended ImageInfo and Image so they know the image type.
* Added DebuggerInterface::GetSymbolInfo(). * Implementing stopping the thread in main() when the debugger started the debugged program. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31393 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#include "Jobs.h"
|
#include "Jobs.h"
|
||||||
#include "LocatableFile.h"
|
#include "LocatableFile.h"
|
||||||
#include "MessageCodes.h"
|
#include "MessageCodes.h"
|
||||||
|
#include "SymbolInfo.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
#include "TeamDebugModel.h"
|
#include "TeamDebugModel.h"
|
||||||
@@ -288,6 +289,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
// get the initial state of the team
|
// get the initial state of the team
|
||||||
AutoLocker< ::Team> teamLocker(fTeam);
|
AutoLocker< ::Team> teamLocker(fTeam);
|
||||||
|
|
||||||
|
ThreadHandler* mainThreadHandler = NULL;
|
||||||
{
|
{
|
||||||
BObjectList<ThreadInfo> threadInfos(20, true);
|
BObjectList<ThreadInfo> threadInfos(20, true);
|
||||||
status_t error = fDebuggerInterface->GetThreadInfos(threadInfos);
|
status_t error = fDebuggerInterface->GetThreadInfos(threadInfos);
|
||||||
@@ -305,17 +307,24 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
|
|
||||||
fThreadHandlers.Insert(handler);
|
fThreadHandlers.Insert(handler);
|
||||||
|
|
||||||
|
if (thread->IsMainThread())
|
||||||
|
mainThreadHandler = handler;
|
||||||
|
|
||||||
handler->Init();
|
handler->Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image* appImage = NULL;
|
||||||
{
|
{
|
||||||
BObjectList<ImageInfo> imageInfos(20, true);
|
BObjectList<ImageInfo> imageInfos(20, true);
|
||||||
status_t error = fDebuggerInterface->GetImageInfos(imageInfos);
|
status_t error = fDebuggerInterface->GetImageInfos(imageInfos);
|
||||||
for (int32 i = 0; ImageInfo* info = imageInfos.ItemAt(i); i++) {
|
for (int32 i = 0; ImageInfo* info = imageInfos.ItemAt(i); i++) {
|
||||||
error = _AddImage(*info);
|
Image* image;
|
||||||
|
error = _AddImage(*info, &image);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
if (image->Type() == B_APP_IMAGE)
|
||||||
|
appImage = image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +357,13 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
|
|||||||
// if requested, stop the given thread
|
// if requested, stop the given thread
|
||||||
if (threadID >= 0) {
|
if (threadID >= 0) {
|
||||||
if (stopInMain) {
|
if (stopInMain) {
|
||||||
// TODO: Set a temporary breakpoint in main and run the thread.
|
SymbolInfo symbolInfo;
|
||||||
|
if (appImage != NULL && mainThreadHandler != NULL
|
||||||
|
&& fDebuggerInterface->GetSymbolInfo(
|
||||||
|
fTeam->ID(), appImage->ID(), "main", B_SYMBOL_TYPE_TEXT,
|
||||||
|
symbolInfo) == B_OK) {
|
||||||
|
mainThreadHandler->SetBreakpointAndRun(symbolInfo.Address());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug_thread(threadID);
|
debug_thread(threadID);
|
||||||
// TODO: Superfluous, if the thread is already stopped.
|
// TODO: Superfluous, if the thread is already stopped.
|
||||||
@@ -852,7 +867,7 @@ TeamDebugger::_GetThreadHandler(thread_id threadID)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
TeamDebugger::_AddImage(const ImageInfo& imageInfo)
|
TeamDebugger::_AddImage(const ImageInfo& imageInfo, Image** _image)
|
||||||
{
|
{
|
||||||
LocatableFile* file = NULL;
|
LocatableFile* file = NULL;
|
||||||
if (strchr(imageInfo.Name(), '/') != NULL)
|
if (strchr(imageInfo.Name(), '/') != NULL)
|
||||||
@@ -868,6 +883,9 @@ TeamDebugger::_AddImage(const ImageInfo& imageInfo)
|
|||||||
if (imageHandler != NULL)
|
if (imageHandler != NULL)
|
||||||
fImageHandlers->Insert(imageHandler);
|
fImageHandlers->Insert(imageHandler);
|
||||||
|
|
||||||
|
if (_image != NULL)
|
||||||
|
*_image = image;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ private:
|
|||||||
|
|
||||||
ThreadHandler* _GetThreadHandler(thread_id threadID);
|
ThreadHandler* _GetThreadHandler(thread_id threadID);
|
||||||
|
|
||||||
status_t _AddImage(const ImageInfo& imageInfo);
|
status_t _AddImage(const ImageInfo& imageInfo,
|
||||||
|
Image** _image = NULL);
|
||||||
|
|
||||||
void _NotifyUser(const char* title,
|
void _NotifyUser(const char* title,
|
||||||
const char* text,...);
|
const char* text,...);
|
||||||
|
|||||||
@@ -70,6 +70,26 @@ ThreadHandler::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ThreadHandler::SetBreakpointAndRun(target_addr_t address)
|
||||||
|
{
|
||||||
|
status_t error = _InstallTemporaryBreakpoint(address);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
fPreviousInstructionPointer = 0;
|
||||||
|
resume_thread(ThreadID());
|
||||||
|
// TODO: This should probably better be a DebuggerInterface method,
|
||||||
|
// but this method is used only when debugging a local team anyway.
|
||||||
|
// Pretend "step out" mode, so that the temporary breakpoint hit will not
|
||||||
|
// be ignored.
|
||||||
|
fStepMode = STEP_OUT;
|
||||||
|
fSingleStepping = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ThreadHandler::HandleThreadDebugged(ThreadDebuggedEvent* event)
|
ThreadHandler::HandleThreadDebugged(ThreadDebuggedEvent* event)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ public:
|
|||||||
thread_id ThreadID() const { return fThread->ID(); }
|
thread_id ThreadID() const { return fThread->ID(); }
|
||||||
Thread* GetThread() const { return fThread; }
|
Thread* GetThread() const { return fThread; }
|
||||||
|
|
||||||
|
status_t SetBreakpointAndRun(target_addr_t address);
|
||||||
|
// team lock held
|
||||||
|
|
||||||
// All Handle*() methods are invoked in team debugger thread,
|
// All Handle*() methods are invoked in team debugger thread,
|
||||||
// looper lock held.
|
// looper lock held.
|
||||||
bool HandleThreadDebugged(
|
bool HandleThreadDebugged(
|
||||||
|
|||||||
@@ -423,8 +423,8 @@ DebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
|
|||||||
int32 cookie = 0;
|
int32 cookie = 0;
|
||||||
while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
|
while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
|
||||||
ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id,
|
ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id,
|
||||||
imageInfo.name, (addr_t)imageInfo.text, imageInfo.text_size,
|
imageInfo.name, imageInfo.type, (addr_t)imageInfo.text,
|
||||||
(addr_t)imageInfo.data, imageInfo.data_size);
|
imageInfo.text_size, (addr_t)imageInfo.data, imageInfo.data_size);
|
||||||
if (info == NULL || !infos.AddItem(info)) {
|
if (info == NULL || !infos.AddItem(info)) {
|
||||||
delete info;
|
delete info;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -438,9 +438,9 @@ DebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
|
|||||||
if ((addr_t)imageInfo.text >= USER_COMMPAGE_ADDR
|
if ((addr_t)imageInfo.text >= USER_COMMPAGE_ADDR
|
||||||
&& (addr_t)imageInfo.text < USER_COMMPAGE_ADDR + COMMPAGE_SIZE) {
|
&& (addr_t)imageInfo.text < USER_COMMPAGE_ADDR + COMMPAGE_SIZE) {
|
||||||
ImageInfo* info = new(std::nothrow) ImageInfo(B_SYSTEM_TEAM,
|
ImageInfo* info = new(std::nothrow) ImageInfo(B_SYSTEM_TEAM,
|
||||||
imageInfo.id, imageInfo.name, (addr_t)imageInfo.text,
|
imageInfo.id, imageInfo.name, imageInfo.type,
|
||||||
imageInfo.text_size, (addr_t)imageInfo.data,
|
(addr_t)imageInfo.text, imageInfo.text_size,
|
||||||
imageInfo.data_size);
|
(addr_t)imageInfo.data, imageInfo.data_size);
|
||||||
if (info == NULL || !infos.AddItem(info)) {
|
if (info == NULL || !infos.AddItem(info)) {
|
||||||
delete info;
|
delete info;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -498,6 +498,36 @@ DebuggerInterface::GetSymbolInfos(team_id team, image_id image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DebuggerInterface::GetSymbolInfo(team_id team, image_id image, const char* name,
|
||||||
|
int32 symbolType, SymbolInfo& info)
|
||||||
|
{
|
||||||
|
// create a lookup context
|
||||||
|
// TODO: It's a bit expensive to create a lookup context just for one
|
||||||
|
// symbol!
|
||||||
|
debug_symbol_lookup_context* lookupContext;
|
||||||
|
status_t error = debug_create_symbol_lookup_context(team, &lookupContext);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// try to get the symbol
|
||||||
|
void* foundAddress;
|
||||||
|
size_t foundSize;
|
||||||
|
int32 foundType;
|
||||||
|
error = debug_get_symbol(lookupContext, image, name, symbolType,
|
||||||
|
&foundAddress, &foundSize, &foundType);
|
||||||
|
if (error == B_OK) {
|
||||||
|
info.SetTo((target_addr_t)(addr_t)foundAddress, foundSize, foundType,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the lookup context
|
||||||
|
debug_delete_symbol_lookup_context(lookupContext);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
|
DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
|
||||||
{
|
{
|
||||||
@@ -638,8 +668,9 @@ DebuggerInterface::_CreateDebugEvent(int32 messageCode,
|
|||||||
const image_info& info = message.image_created.info;
|
const image_info& info = message.image_created.info;
|
||||||
event = new(std::nothrow) ImageCreatedEvent(message.origin.team,
|
event = new(std::nothrow) ImageCreatedEvent(message.origin.team,
|
||||||
message.origin.thread,
|
message.origin.thread,
|
||||||
ImageInfo(fTeamID, info.id, info.name, (addr_t)info.text,
|
ImageInfo(fTeamID, info.id, info.name, info.type,
|
||||||
info.text_size, (addr_t)info.data, info.data_size));
|
(addr_t)info.text, info.text_size, (addr_t)info.data,
|
||||||
|
info.data_size));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
|
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
|
||||||
@@ -647,8 +678,9 @@ DebuggerInterface::_CreateDebugEvent(int32 messageCode,
|
|||||||
const image_info& info = message.image_deleted.info;
|
const image_info& info = message.image_deleted.info;
|
||||||
event = new(std::nothrow) ImageDeletedEvent(message.origin.team,
|
event = new(std::nothrow) ImageDeletedEvent(message.origin.team,
|
||||||
message.origin.thread,
|
message.origin.thread,
|
||||||
ImageInfo(fTeamID, info.id, info.name, (addr_t)info.text,
|
ImageInfo(fTeamID, info.id, info.name, info.type,
|
||||||
info.text_size, (addr_t)info.data, info.data_size));
|
(addr_t)info.text, info.text_size, (addr_t)info.data,
|
||||||
|
info.data_size));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ public:
|
|||||||
virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos);
|
virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos);
|
||||||
virtual status_t GetSymbolInfos(team_id team, image_id image,
|
virtual status_t GetSymbolInfos(team_id team, image_id image,
|
||||||
BObjectList<SymbolInfo>& infos);
|
BObjectList<SymbolInfo>& infos);
|
||||||
|
virtual status_t GetSymbolInfo(team_id team, image_id image,
|
||||||
|
const char* name, int32 symbolType,
|
||||||
|
SymbolInfo& info);
|
||||||
|
|
||||||
virtual status_t GetThreadInfo(thread_id thread,
|
virtual status_t GetThreadInfo(thread_id thread,
|
||||||
ThreadInfo& info);
|
ThreadInfo& info);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public:
|
|||||||
image_id ID() const { return fInfo.ImageID(); }
|
image_id ID() const { return fInfo.ImageID(); }
|
||||||
const char* Name() const { return fInfo.Name(); }
|
const char* Name() const { return fInfo.Name(); }
|
||||||
const ImageInfo& Info() const { return fInfo; }
|
const ImageInfo& Info() const { return fInfo; }
|
||||||
|
image_type Type() const { return fInfo.Type(); }
|
||||||
LocatableFile* ImageFile() const { return fImageFile; }
|
LocatableFile* ImageFile() const { return fImageFile; }
|
||||||
|
|
||||||
bool ContainsAddress(target_addr_t address) const;
|
bool ContainsAddress(target_addr_t address) const;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ ImageInfo::ImageInfo(const ImageInfo& other)
|
|||||||
fTeam(other.fTeam),
|
fTeam(other.fTeam),
|
||||||
fImage(other.fImage),
|
fImage(other.fImage),
|
||||||
fName(other.fName),
|
fName(other.fName),
|
||||||
|
fType(other.fType),
|
||||||
fTextBase(other.fTextBase),
|
fTextBase(other.fTextBase),
|
||||||
fTextSize(other.fTextSize),
|
fTextSize(other.fTextSize),
|
||||||
fDataBase(other.fDataBase),
|
fDataBase(other.fDataBase),
|
||||||
@@ -32,12 +33,13 @@ ImageInfo::ImageInfo(const ImageInfo& other)
|
|||||||
|
|
||||||
|
|
||||||
ImageInfo::ImageInfo(team_id team, image_id image, const BString& name,
|
ImageInfo::ImageInfo(team_id team, image_id image, const BString& name,
|
||||||
target_addr_t textBase, target_size_t textSize, target_addr_t dataBase,
|
image_type type, target_addr_t textBase, target_size_t textSize,
|
||||||
target_size_t dataSize)
|
target_addr_t dataBase, target_size_t dataSize)
|
||||||
:
|
:
|
||||||
fTeam(team),
|
fTeam(team),
|
||||||
fImage(image),
|
fImage(image),
|
||||||
fName(name),
|
fName(name),
|
||||||
|
fType(type),
|
||||||
fTextBase(textBase),
|
fTextBase(textBase),
|
||||||
fTextSize(textSize),
|
fTextSize(textSize),
|
||||||
fDataBase(dataBase),
|
fDataBase(dataBase),
|
||||||
@@ -48,12 +50,13 @@ ImageInfo::ImageInfo(team_id team, image_id image, const BString& name,
|
|||||||
|
|
||||||
void
|
void
|
||||||
ImageInfo::SetTo(team_id team, image_id image, const BString& name,
|
ImageInfo::SetTo(team_id team, image_id image, const BString& name,
|
||||||
target_addr_t textBase, target_size_t textSize, target_addr_t dataBase,
|
image_type type, target_addr_t textBase, target_size_t textSize,
|
||||||
target_size_t dataSize)
|
target_addr_t dataBase, target_size_t dataSize)
|
||||||
{
|
{
|
||||||
fTeam = team;
|
fTeam = team;
|
||||||
fImage = image;
|
fImage = image;
|
||||||
fName = name;
|
fName = name;
|
||||||
|
fType = type;
|
||||||
fTextBase = textBase;
|
fTextBase = textBase;
|
||||||
fTextSize = textSize;
|
fTextSize = textSize;
|
||||||
fDataBase = dataBase;
|
fDataBase = dataBase;
|
||||||
|
|||||||
@@ -16,14 +16,14 @@ public:
|
|||||||
ImageInfo();
|
ImageInfo();
|
||||||
ImageInfo(const ImageInfo& other);
|
ImageInfo(const ImageInfo& other);
|
||||||
ImageInfo(team_id team, image_id image,
|
ImageInfo(team_id team, image_id image,
|
||||||
const BString& name,
|
const BString& name, image_type type,
|
||||||
target_addr_t textBase,
|
target_addr_t textBase,
|
||||||
target_size_t textSize,
|
target_size_t textSize,
|
||||||
target_addr_t dataBase,
|
target_addr_t dataBase,
|
||||||
target_size_t dataSize);
|
target_size_t dataSize);
|
||||||
|
|
||||||
void SetTo(team_id team, image_id image,
|
void SetTo(team_id team, image_id image,
|
||||||
const BString& name,
|
const BString& name, image_type type,
|
||||||
target_addr_t textBase,
|
target_addr_t textBase,
|
||||||
target_size_t textSize,
|
target_size_t textSize,
|
||||||
target_addr_t dataBase,
|
target_addr_t dataBase,
|
||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
team_id TeamID() const { return fTeam; }
|
team_id TeamID() const { return fTeam; }
|
||||||
image_id ImageID() const { return fImage; }
|
image_id ImageID() const { return fImage; }
|
||||||
const char* Name() const { return fName.String(); }
|
const char* Name() const { return fName.String(); }
|
||||||
|
image_type Type() const { return fType; }
|
||||||
|
|
||||||
target_addr_t TextBase() const { return fTextBase; }
|
target_addr_t TextBase() const { return fTextBase; }
|
||||||
target_size_t TextSize() const { return fTextSize; }
|
target_size_t TextSize() const { return fTextSize; }
|
||||||
@@ -42,6 +43,7 @@ private:
|
|||||||
thread_id fTeam;
|
thread_id fTeam;
|
||||||
image_id fImage;
|
image_id fImage;
|
||||||
BString fName;
|
BString fName;
|
||||||
|
image_type fType;
|
||||||
target_addr_t fTextBase;
|
target_addr_t fTextBase;
|
||||||
target_size_t fTextSize;
|
target_size_t fTextSize;
|
||||||
target_addr_t fDataBase;
|
target_addr_t fDataBase;
|
||||||
|
|||||||
@@ -6,6 +6,16 @@
|
|||||||
#include "SymbolInfo.h"
|
#include "SymbolInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
SymbolInfo::SymbolInfo()
|
||||||
|
:
|
||||||
|
fAddress(0),
|
||||||
|
fSize(0),
|
||||||
|
fType(0),
|
||||||
|
fName()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SymbolInfo::SymbolInfo(target_addr_t address, target_size_t size, uint32 type,
|
SymbolInfo::SymbolInfo(target_addr_t address, target_size_t size, uint32 type,
|
||||||
const BString& name)
|
const BString& name)
|
||||||
:
|
:
|
||||||
@@ -20,3 +30,14 @@ SymbolInfo::SymbolInfo(target_addr_t address, target_size_t size, uint32 type,
|
|||||||
SymbolInfo::~SymbolInfo()
|
SymbolInfo::~SymbolInfo()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SymbolInfo::SetTo(target_addr_t address, target_size_t size, uint32 type,
|
||||||
|
const BString& name)
|
||||||
|
{
|
||||||
|
fAddress = address;
|
||||||
|
fSize = size;
|
||||||
|
fType = type;
|
||||||
|
fName = name;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,11 +12,15 @@
|
|||||||
|
|
||||||
class SymbolInfo {
|
class SymbolInfo {
|
||||||
public:
|
public:
|
||||||
|
SymbolInfo();
|
||||||
SymbolInfo(target_addr_t address,
|
SymbolInfo(target_addr_t address,
|
||||||
target_size_t size, uint32 type,
|
target_size_t size, uint32 type,
|
||||||
const BString& name);
|
const BString& name);
|
||||||
~SymbolInfo();
|
~SymbolInfo();
|
||||||
|
|
||||||
|
void SetTo(target_addr_t address, target_size_t size,
|
||||||
|
uint32 type, const BString& name);
|
||||||
|
|
||||||
target_addr_t Address() const { return fAddress; }
|
target_addr_t Address() const { return fAddress; }
|
||||||
target_size_t Size() const { return fSize; }
|
target_size_t Size() const { return fSize; }
|
||||||
uint32 Type() const { return fType; }
|
uint32 Type() const { return fType; }
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ Thread::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Thread::IsMainThread() const
|
||||||
|
{
|
||||||
|
return fID == fTeam->ID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::SetName(const BString& name)
|
Thread::SetName(const BString& name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public:
|
|||||||
Team* GetTeam() const { return fTeam; }
|
Team* GetTeam() const { return fTeam; }
|
||||||
thread_id ID() const { return fID; }
|
thread_id ID() const { return fID; }
|
||||||
|
|
||||||
|
bool IsMainThread() const;
|
||||||
|
|
||||||
const char* Name() const { return fName.String(); }
|
const char* Name() const { return fName.String(); }
|
||||||
void SetName(const BString& name);
|
void SetName(const BString& name);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user