1
by damienlmoore at gmail
Code::Blocks 16.01 |
1 |
#include "Addr2LineUIMain.h" |
2 |
||
3 |
//(*InternalHeaders(Addr2LineUIDialog)
|
|
4 |
#include <wx/settings.h> |
|
5 |
#include <wx/font.h> |
|
6 |
#include <wx/intl.h> |
|
7 |
#include <wx/string.h> |
|
8 |
//*)
|
|
9 |
||
10 |
#include <wx/busyinfo.h> |
|
11 |
#include <wx/msgdlg.h> |
|
12 |
#include <wx/regex.h> |
|
13 |
#include <wx/textfile.h> |
|
14 |
#include <wx/utils.h> // wxExecute |
|
15 |
||
16 |
//(*IdInit(Addr2LineUIDialog)
|
|
17 |
const long Addr2LineUIDialog::ID_CRASH_LOG = wxNewId(); |
|
18 |
const long Addr2LineUIDialog::ID_ADDR2LINE = wxNewId(); |
|
19 |
const long Addr2LineUIDialog::ID_DIR_PREPEND = wxNewId(); |
|
20 |
const long Addr2LineUIDialog::ID_CHK_REPLACE = wxNewId(); |
|
21 |
const long Addr2LineUIDialog::ID_TXT_REPLACE_THIS = wxNewId(); |
|
22 |
const long Addr2LineUIDialog::ID_LBL_REPLACE = wxNewId(); |
|
23 |
const long Addr2LineUIDialog::ID_TXT_REPLACE_THAT = wxNewId(); |
|
24 |
const long Addr2LineUIDialog::ID_CHK_SKIP_UNRESOLVABLE = wxNewId(); |
|
25 |
const long Addr2LineUIDialog::ID_TXT_CRASH_LOG_CONTENT = wxNewId(); |
|
26 |
const long Addr2LineUIDialog::ID_TXT_RESULT = wxNewId(); |
|
27 |
const long Addr2LineUIDialog::ID_BTN_OPERATE = wxNewId(); |
|
28 |
const long Addr2LineUIDialog::ID_BTN_QUIT = wxNewId(); |
|
29 |
//*)
|
|
30 |
||
31 |
BEGIN_EVENT_TABLE(Addr2LineUIDialog,wxDialog) |
|
32 |
//(*EventTable(Addr2LineUIDialog)
|
|
33 |
//*)
|
|
34 |
END_EVENT_TABLE() |
|
35 |
||
36 |
Addr2LineUIDialog::Addr2LineUIDialog(wxWindow* parent) : |
|
37 |
mFileConfig(), |
|
38 |
mCrashLog(), |
|
39 |
mCrashLogFileContent(), |
|
40 |
mAddr2Line(wxT("addr2line")), |
|
41 |
mDirPrepend() |
|
42 |
{
|
|
43 |
//(*Initialize(Addr2LineUIDialog)
|
|
44 |
wxStaticText* lblDirPrepend; |
|
45 |
wxBoxSizer* bszAddr2Line; |
|
46 |
wxButton* btnQuit; |
|
47 |
wxBoxSizer* bszMainV; |
|
48 |
wxStaticText* lblCrashLog; |
|
49 |
wxBoxSizer* bszReplace; |
|
50 |
wxBoxSizer* bszMainH; |
|
51 |
wxStaticText* lblAddr2Line; |
|
52 |
wxStaticLine* stlLine; |
|
53 |
||
54 |
Create(parent, wxID_ANY, _("Addr2LineUI"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX, _T("wxID_ANY")); |
|
55 |
bszMainH = new wxBoxSizer(wxHORIZONTAL); |
|
56 |
bszMainV = new wxBoxSizer(wxVERTICAL); |
|
57 |
bszAddr2Line = new wxBoxSizer(wxVERTICAL); |
|
58 |
lblCrashLog = new wxStaticText(this, wxID_ANY, _("Select crash log file:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY")); |
|
59 |
bszAddr2Line->Add(lblCrashLog, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
60 |
m_FPCrashLog = new wxFilePickerCtrl(this, ID_CRASH_LOG, wxEmptyString, _("Select crash log"), _T("Report files (*.rpt)|*.rpt|Log files (*.log)|*.log|All files (*.*)|*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_CRASH_LOG")); |
|
61 |
bszAddr2Line->Add(m_FPCrashLog, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
62 |
lblAddr2Line = new wxStaticText(this, wxID_ANY, _("Select Addr2Line tool:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY")); |
|
63 |
bszAddr2Line->Add(lblAddr2Line, 0, wxTOP|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
64 |
m_FPAddr2Line = new wxFilePickerCtrl(this, ID_ADDR2LINE, wxEmptyString, _("Select addr2line tool"), _T("Executables (*.exe)|*.exe|All files (*.*)|*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_ADDR2LINE")); |
|
65 |
bszAddr2Line->Add(m_FPAddr2Line, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
66 |
lblDirPrepend = new wxStaticText(this, wxID_ANY, _("(Optionally) Select directory to prepend:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY")); |
|
67 |
bszAddr2Line->Add(lblDirPrepend, 0, wxTOP|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
68 |
m_DPDirPrepend = new wxDirPickerCtrl(this, ID_DIR_PREPEND, wxEmptyString, _("Select directory to prepend"), wxDefaultPosition, wxDefaultSize, wxDIRP_DIR_MUST_EXIST|wxDIRP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_DIR_PREPEND")); |
|
69 |
bszAddr2Line->Add(m_DPDirPrepend, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
70 |
bszMainV->Add(bszAddr2Line, 0, wxALL|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
71 |
bszReplace = new wxBoxSizer(wxHORIZONTAL); |
|
72 |
chkReplace = new wxCheckBox(this, ID_CHK_REPLACE, _("Replace:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHK_REPLACE")); |
|
73 |
chkReplace->SetValue(false); |
|
74 |
bszReplace->Add(chkReplace, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
75 |
txtReplaceThis = new wxTextCtrl(this, ID_TXT_REPLACE_THIS, _("this"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TXT_REPLACE_THIS")); |
|
76 |
txtReplaceThis->Disable(); |
|
77 |
bszReplace->Add(txtReplaceThis, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
78 |
lblReplace = new wxStaticText(this, ID_LBL_REPLACE, _("...with:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_LBL_REPLACE")); |
|
79 |
lblReplace->Disable(); |
|
80 |
bszReplace->Add(lblReplace, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5); |
|
81 |
txtReplaceThat = new wxTextCtrl(this, ID_TXT_REPLACE_THAT, _("that"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TXT_REPLACE_THAT")); |
|
82 |
txtReplaceThat->Disable(); |
|
83 |
bszReplace->Add(txtReplaceThat, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
84 |
chkSkipUnresolvable = new wxCheckBox(this, ID_CHK_SKIP_UNRESOLVABLE, _("Skip unresolvable"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHK_SKIP_UNRESOLVABLE")); |
|
85 |
chkSkipUnresolvable->SetValue(false); |
|
86 |
bszReplace->Add(chkSkipUnresolvable, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); |
|
87 |
bszMainV->Add(bszReplace, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
88 |
txtCrashLogContent = new wxTextCtrl(this, ID_TXT_CRASH_LOG_CONTENT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE, wxDefaultValidator, _T("ID_TXT_CRASH_LOG_CONTENT")); |
|
89 |
txtCrashLogContent->SetMinSize(wxSize(450,200)); |
|
90 |
wxFont txtCrashLogContentFont = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT); |
|
91 |
if ( !txtCrashLogContentFont.Ok() ) txtCrashLogContentFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); |
|
92 |
txtCrashLogContent->SetFont(txtCrashLogContentFont); |
|
93 |
bszMainV->Add(txtCrashLogContent, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
94 |
txtResult = new wxTextCtrl(this, ID_TXT_RESULT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE, wxDefaultValidator, _T("ID_TXT_RESULT")); |
|
95 |
txtResult->SetMinSize(wxSize(450,200)); |
|
96 |
wxFont txtResultFont = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT); |
|
97 |
if ( !txtResultFont.Ok() ) txtResultFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); |
|
98 |
txtResult->SetFont(txtResultFont); |
|
99 |
bszMainV->Add(txtResult, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
100 |
stlLine = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxSize(10,-1), wxLI_HORIZONTAL, _T("wxID_ANY")); |
|
101 |
bszMainV->Add(stlLine, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5); |
|
102 |
btnOperate = new wxButton(this, ID_BTN_OPERATE, _("Operate"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BTN_OPERATE")); |
|
103 |
btnOperate->Disable(); |
|
104 |
bszMainV->Add(btnOperate, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_TOP|wxALIGN_CENTER_HORIZONTAL, 5); |
|
105 |
btnQuit = new wxButton(this, ID_BTN_QUIT, _("Quit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BTN_QUIT")); |
|
106 |
bszMainV->Add(btnQuit, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_TOP|wxALIGN_CENTER_HORIZONTAL, 5); |
|
107 |
bszMainH->Add(bszMainV, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4); |
|
108 |
SetSizer(bszMainH); |
|
109 |
bszMainH->Fit(this); |
|
110 |
bszMainH->SetSizeHints(this); |
|
111 |
||
112 |
Connect(ID_CRASH_LOG,wxEVT_COMMAND_FILEPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnCrashLogFile)); |
|
113 |
Connect(ID_ADDR2LINE,wxEVT_COMMAND_FILEPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnAddr2LineFile)); |
|
114 |
Connect(ID_DIR_PREPEND,wxEVT_COMMAND_DIRPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnDirPrependDir)); |
|
115 |
Connect(ID_CHK_REPLACE,wxEVT_COMMAND_CHECKBOX_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnReplaceClick)); |
|
116 |
Connect(ID_BTN_OPERATE,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnOperateClick)); |
|
117 |
Connect(ID_BTN_QUIT,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnQuit)); |
|
118 |
//*)
|
|
119 |
||
120 |
mFileConfig.Read(wxT("CrashLog"), &mCrashLog, wxT("")); m_FPCrashLog->SetPath(mCrashLog); |
|
121 |
mFileConfig.Read(wxT("Addr2Line"), &mAddr2Line, wxT("")); m_FPAddr2Line->SetPath(mAddr2Line); |
|
122 |
mFileConfig.Read(wxT("DirPrepend"), &mDirPrepend, wxT("")); m_DPDirPrepend->SetPath(mDirPrepend); |
|
123 |
||
124 |
bool Replace; mFileConfig.Read(wxT("Replace"), &Replace, false ); chkReplace->SetValue(Replace); |
|
125 |
if (Replace) { txtReplaceThis->Enable(); lblReplace->Enable(); txtReplaceThat->Enable(); } |
|
126 |
wxString ReplaceThis; mFileConfig.Read(wxT("ReplaceThis"), &ReplaceThis, wxT("")); txtReplaceThis->SetValue(ReplaceThis); |
|
127 |
wxString ReplaceThat; mFileConfig.Read(wxT("ReplaceThat"), &ReplaceThat, wxT("")); txtReplaceThat->SetValue(ReplaceThat); |
|
128 |
||
129 |
bool SkipUnresolvable; mFileConfig.Read(wxT("SkipUnresolvable"), &SkipUnresolvable, false ); chkSkipUnresolvable->SetValue(SkipUnresolvable); |
|
130 |
}
|
|
131 |
||
132 |
Addr2LineUIDialog::~Addr2LineUIDialog() |
|
133 |
{
|
|
134 |
//(*Destroy(Addr2LineUIDialog)
|
|
135 |
//*)
|
|
136 |
}
|
|
137 |
||
138 |
void Addr2LineUIDialog::OnCrashLogFile(wxFileDirPickerEvent& event) |
|
139 |
{
|
|
140 |
mCrashLog = event.GetPath(); |
|
141 |
||
142 |
wxTextFile file(mCrashLog); |
|
143 |
if (file.Open()) |
|
144 |
{
|
|
145 |
mCrashLogFileContent.Clear(); |
|
146 |
txtCrashLogContent->Clear(); |
|
147 |
for (wxString line = file.GetFirstLine(); !file.Eof(); line = file.GetNextLine()) |
|
148 |
{
|
|
149 |
mCrashLogFileContent.Add(line); |
|
150 |
txtCrashLogContent->AppendText(line + wxT("\n")); |
|
151 |
}
|
|
152 |
||
153 |
if (mCrashLogFileContent.Count()>0) btnOperate->Enable(); else btnOperate->Disable(); |
|
154 |
}
|
|
155 |
else
|
|
156 |
wxMessageBox(wxT("Error: File could not be opened."), wxT("Addr2LineUI"), wxOK|wxICON_ERROR, this); |
|
157 |
}
|
|
158 |
||
159 |
void Addr2LineUIDialog::OnAddr2LineFile(wxFileDirPickerEvent& event) |
|
160 |
{
|
|
161 |
mAddr2Line = event.GetPath(); |
|
162 |
}
|
|
163 |
||
164 |
void Addr2LineUIDialog::OnDirPrependDir(wxFileDirPickerEvent& event) |
|
165 |
{
|
|
166 |
mDirPrepend = event.GetPath(); |
|
167 |
}
|
|
168 |
||
169 |
void Addr2LineUIDialog::OnReplaceClick(wxCommandEvent& event) |
|
170 |
{
|
|
171 |
if (event.IsChecked()) |
|
172 |
{ txtReplaceThis->Enable(); lblReplace->Enable(); txtReplaceThat->Enable(); } |
|
173 |
else
|
|
174 |
{ txtReplaceThis->Disable(); lblReplace->Disable(); txtReplaceThat->Disable(); } |
|
175 |
}
|
|
176 |
||
177 |
void Addr2LineUIDialog::OnOperateClick(wxCommandEvent& WXUNUSED(event)) |
|
178 |
{
|
|
179 |
// Style w/ debug symbols:
|
|
180 |
/*
|
|
181 |
004013AE 00000008 60000000 40166666 sample_d.exe!Function [C:\Devel\CodeBlocks\MinGW\bin\DrMinGW\demo/sample.cpp @ 10]
|
|
182 |
...
|
|
183 |
||
184 |
static void Function(int i, double j, const char * pszString) {
|
|
185 |
> sscanf("12345", "%i", (int *)1);
|
|
186 |
}
|
|
187 |
||
188 |
...
|
|
189 |
||
190 |
00401CCE 00000004 40B33333 0028FF08 sample_d.exe!StaticMethod [C:\Devel\CodeBlocks\MinGW\bin\DrMinGW\demo/sample.cpp @ 15]
|
|
191 |
...
|
|
192 |
struct Class {
|
|
193 |
static void StaticMethod(int i, float j) {
|
|
194 |
> Function(i * 2, j, "Hello");
|
|
195 |
}
|
|
196 |
||
197 |
...
|
|
198 |
*/
|
|
199 |
||
200 |
// Sytle w/o debug symbols:
|
|
201 |
/*
|
|
202 |
004013AE 00000008 60000000 40166666 sample_r.exe!Function(int, double, char const*)
|
|
203 |
00401CCE 00000004 40B33333 0028FF08 sample_r.exe!Class::StaticMethod(int, float)
|
|
204 |
*/
|
|
205 |
||
206 |
// The address element "XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX " needs to be removed later, compute size here.
|
|
207 |
wxRegEx reAddr32(wxT("([A-Fa-f0-9]{8})")); wxString tag32(wxT("AddrPC Params")); size_t len32 = 4*8 +4; // 4 times 8bit address + 4 times space |
|
208 |
wxRegEx reAddr64(wxT("([A-Fa-f0-9]{16})")); wxString tag64(wxT("AddrPC Params")); size_t len64 = 4*16+4; // 4 times 16bit address + 4 times space |
|
209 |
bool is64Bit = false; |
|
210 |
txtResult->Clear(); |
|
211 |
||
212 |
txtResult->AppendText(wxT("Working directory is '") + wxGetCwd() + wxT("'.\n")); |
|
213 |
||
214 |
||
215 |
bool operate_line = false; |
|
216 |
for (size_t i=0; i<mCrashLogFileContent.Count(); i++) |
|
217 |
{
|
|
218 |
wxString line = mCrashLogFileContent.Item(i); |
|
219 |
if (line.IsSameAs(tag32)) |
|
220 |
{
|
|
221 |
txtResult->AppendText(wxT("*************************************\n")); |
|
222 |
txtResult->AppendText(wxT("* Found (another) 32 bit call stack *\n")); |
|
223 |
txtResult->AppendText(wxT("*************************************\n")); |
|
224 |
operate_line = true; |
|
225 |
continue; |
|
226 |
}
|
|
227 |
else if (line.IsSameAs(tag64)) |
|
228 |
{
|
|
229 |
txtResult->AppendText(wxT("*************************************\n")); |
|
230 |
txtResult->AppendText(wxT("* Found (another) 64 bit call stack *\n")); |
|
231 |
txtResult->AppendText(wxT("*************************************\n")); |
|
232 |
operate_line = true; |
|
233 |
is64Bit = true; |
|
234 |
continue; |
|
235 |
}
|
|
236 |
||
237 |
if (!operate_line) |
|
238 |
continue; |
|
239 |
||
240 |
line = line.Trim(true).Trim(false); |
|
241 |
if (line.IsEmpty()) |
|
242 |
continue; |
|
243 |
||
244 |
if (!is64Bit && !reAddr32.Matches(line) ) |
|
245 |
continue; |
|
246 |
if ( is64Bit && !reAddr64.Matches(line) ) |
|
247 |
continue; |
|
248 |
||
249 |
wxString theAddr; |
|
250 |
wxString theFile; |
|
251 |
||
252 |
||
253 |
// Obtain address
|
|
254 |
if (is64Bit) |
|
255 |
{
|
|
256 |
for (size_t j=1; j<=reAddr64.GetMatchCount(); j++) |
|
257 |
{
|
|
258 |
switch (j) |
|
259 |
{
|
|
260 |
case 1: { theAddr = reAddr64.GetMatch(line, 1); } break; |
|
261 |
case 2: // fall through |
|
262 |
case 3: // fall through |
|
263 |
case 4: // fall through |
|
264 |
default: break; |
|
265 |
}
|
|
266 |
}
|
|
267 |
}
|
|
268 |
else // 32 bit |
|
269 |
{
|
|
270 |
for (size_t j=1; j<=reAddr32.GetMatchCount(); j++) |
|
271 |
{
|
|
272 |
switch (j) |
|
273 |
{
|
|
274 |
case 1: { theAddr = reAddr32.GetMatch(line, 1); } break; |
|
275 |
case 2: // fall through |
|
276 |
case 3: // fall through |
|
277 |
case 4: // fall through |
|
278 |
default: break; |
|
279 |
}
|
|
280 |
}
|
|
281 |
}
|
|
282 |
||
283 |
// Verify address
|
|
284 |
if (theAddr.IsEmpty()) |
|
285 |
{
|
|
286 |
txtResult->AppendText(wxT("Skipping empty address '") + line + wxT("'\n")); |
|
287 |
continue; |
|
288 |
}
|
|
289 |
||
290 |
// Remove "XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX "
|
|
291 |
line = line.Right(line.Length() - (is64Bit ? len64 : len32)).Trim(true).Trim(false) ; // 8 times address + 8 times space |
|
292 |
wxString sep = wxT("!"); |
|
293 |
int sep_pos = line.Find(wxT('!'), true); |
|
294 |
if (sep_pos!=wxNOT_FOUND) |
|
295 |
theFile = line.SubString(0,sep_pos-1); |
|
296 |
||
297 |
// Verify file
|
|
298 |
if (theFile.IsEmpty()) |
|
299 |
{
|
|
300 |
txtResult->AppendText(wxT("Skipping address '") + theAddr + wxT("' for unknown file : '") + theFile + wxT("'\n")); |
|
301 |
continue; |
|
302 |
}
|
|
303 |
||
304 |
// prepend directory if requested
|
|
305 |
if (!mDirPrepend.IsEmpty()) |
|
306 |
theFile = mDirPrepend + wxFILE_SEP_PATH + theFile; |
|
307 |
||
308 |
// replacements in command (if any):
|
|
309 |
if (chkReplace->IsChecked()) |
|
310 |
{
|
|
311 |
wxString repl_this = txtReplaceThis->GetValue(); |
|
312 |
wxString repl_that = txtReplaceThat->GetValue(); |
|
313 |
// avoid endless loops
|
|
314 |
if ( !repl_this.IsSameAs(repl_that) |
|
315 |
&& !( repl_this.Trim(true).Trim(false).IsEmpty() |
|
316 |
&& repl_that.Trim(true).Trim(false).IsEmpty() ) |
|
317 |
&& !(repl_this.Trim(true).Trim(false).IsSameAs( |
|
318 |
repl_that.Trim(true).Trim(false)) ) ) |
|
319 |
{
|
|
320 |
theFile.Replace(repl_this, repl_that); |
|
321 |
}
|
|
322 |
else
|
|
323 |
{
|
|
324 |
wxMessageBox(wxT("Error: Invalid setup for replacements (would cause a loop)."), wxT("Addr2LineUI"), wxOK|wxICON_ERROR, this); |
|
325 |
chkReplace->SetValue(false); |
|
326 |
}
|
|
327 |
}
|
|
328 |
||
329 |
if ( !wxFileExists(theFile) ) |
|
330 |
{
|
|
331 |
txtResult->AppendText(wxT("Skipping non-existent file '") + theFile + wxT("'\n")); |
|
332 |
continue; |
|
333 |
}
|
|
334 |
||
335 |
// apply file mask if needed
|
|
336 |
if (theFile.Contains(wxT(" "))) theFile = wxT("\"") + theFile + wxT("\""); |
|
337 |
||
338 |
// compute (initial) command line argument to addr2line
|
|
339 |
wxString command_args = wxT(" -C -e ") + theFile + wxT(" ") + theAddr; |
|
340 |
// Now prepend the addr2line tool and compile the full command
|
|
341 |
wxString command = mAddr2Line + command_args; |
|
342 |
||
343 |
{ // BEGIN Lifetime of wxWindowDisabler and wxBusyInfo |
|
344 |
wxWindowDisabler disableAll; |
|
345 |
wxBusyInfo wait(wxT("Please wait, operating:\n") + command); |
|
346 |
||
347 |
wxArrayString output, error; |
|
348 |
long ret = wxExecute(command, output, error); // sync process |
|
349 |
if (ret==-1) |
|
350 |
{
|
|
351 |
txtResult->AppendText(command + wxT(":\n")); |
|
352 |
txtResult->AppendText(wxT("-1 for: ") + command + wxT("\n")); |
|
353 |
txtResult->AppendText(wxT("----------------------------------------\n")); |
|
354 |
}
|
|
355 |
else if (!error.IsEmpty()) |
|
356 |
{
|
|
357 |
txtResult->AppendText(command + wxT(":\n")); |
|
358 |
txtResult->AppendText(wxT("Error for: ") + command + wxT("\n:")); |
|
359 |
for (size_t j=0; j<error.Count(); j++) |
|
360 |
txtResult->AppendText(error.Item(j) + wxT("\n")); |
|
361 |
txtResult->AppendText(wxT("----------------------------------------\n")); |
|
362 |
}
|
|
363 |
else
|
|
364 |
{
|
|
365 |
bool do_show = true; |
|
366 |
if (chkSkipUnresolvable->IsChecked()) |
|
367 |
{
|
|
368 |
if (output.Count()>0 && output.Item(0).Contains(wxT("??:0"))) |
|
369 |
do_show = false; |
|
370 |
}
|
|
371 |
||
372 |
if (do_show) |
|
373 |
{
|
|
374 |
txtResult->AppendText(command + wxT(":\n")); |
|
375 |
txtResult->AppendText(theFile + wxT("[") + theAddr + wxT("]:\n")); |
|
376 |
for (size_t j=0; j<output.Count(); j++) |
|
377 |
txtResult->AppendText(output.Item(j) + wxT("\n")); |
|
378 |
txtResult->AppendText(wxT("----------------------------------------\n")); |
|
379 |
}
|
|
380 |
}
|
|
381 |
}// END Lifetime of wxWindowDisabler and wxBusyInfo |
|
382 |
}// for |
|
383 |
}
|
|
384 |
||
385 |
void Addr2LineUIDialog::OnQuit(wxCommandEvent& WXUNUSED(event)) |
|
386 |
{
|
|
387 |
mFileConfig.Write(wxT("CrashLog"), mCrashLog ); |
|
388 |
mFileConfig.Write(wxT("Addr2Line"), mAddr2Line ); |
|
389 |
mFileConfig.Write(wxT("DirPrepend"), mDirPrepend ); |
|
390 |
mFileConfig.Write(wxT("Replace"), chkReplace->IsChecked() ); |
|
391 |
mFileConfig.Write(wxT("ReplaceThis"), txtReplaceThis->GetValue() ); |
|
392 |
mFileConfig.Write(wxT("ReplaceThat"), txtReplaceThat->GetValue() ); |
|
393 |
mFileConfig.Write(wxT("SkipUnresolvable"), chkSkipUnresolvable->IsChecked()); |
|
394 |
||
395 |
EndModal(wxID_OK); |
|
396 |
Destroy(); |
|
397 |
}
|