Come estrarre le informazioni sulle variabili locali (indirizzo e tipo) da un programma Delphi o dalle informazioni di debug generate dal compilatore?


105

Il mio obiettivo è:

  • Dato un thread sospeso in un programma Windows a 32 o 64 bit compilato da Delphi, per camminare sullo stack (fattibile)
  • Date le voci dello stack, per enumerare le variabili locali in ciascun metodo e i loro valori. Cioè, come minimo, trova il loro indirizzo e tipo (integer32 / 64 / signed / unsigned, string, float, record, class ...) la cui combinazione può essere usata per trovare il loro valore.

Il primo va bene ed è il secondo di cui tratta questa domanda. Ad alto livello, come enumerare le variabili locali data una voce dello stack in Delphi?


A un livello basso, questo è ciò su cui sto indagando:

RTTI: non elenca questo tipo di informazioni sui metodi. Questo non era qualcosa che in realtà ho mai pensato fosse un'opzione realistica, ma elencare qui comunque.

Informazioni di debug: caricamento delle informazioni di debug prodotte per una build di debug.

  • File mappa: anche un file mappa dettagliato (un file in formato testo! Aprine uno e guarda) non contiene informazioni sulle variabili locali. È fondamentalmente un elenco di indirizzi e numeri di riga del file di origine. Ottimo per la correlazione tra indirizzo e file e linea, ad esempio i punti blu nella grondaia; non eccezionale per informazioni più dettagliate
  • Informazioni di debug remoto (file RSM): nessuna informazione nota sul suo contenuto o formato.
  • File TD32 / TDS: la mia attuale linea di ricerca. Contengono simboli globali e locali tra molte altre informazioni.

I problemi che sto riscontrando qui sono:

  • Non c'è documentazione del formato di file TD32 (che posso trovare).
  • La maggior parte della mia conoscenza su di loro deriva dal codice Jedi JCL che li utilizza (JclTD32.pas) e non sono sicuro di come utilizzare quel codice o se le strutture sono abbastanza ampie da mostrare le variabili locali. Sono abbastanza certo che gestirà simboli globali, ma sono molto incerto sul locale. Ci sono un'ampia varietà di costanti definite e senza documentazione per il formato, per leggere cosa significano, non mi resta che indovinare. Tuttavia, quelle costanti e i loro nomi devono provenire da qualche parte.
  • La fonte che riesco a trovare utilizzando le informazioni TDS non carica o gestisce i simboli locali.

Se questo è l'approccio giusto, la domanda diventa "Esiste documentazione per il formato di file TDS / TD32 e ci sono esempi di codice che caricano variabili locali?"

Un esempio di codice non è essenziale ma potrebbe essere molto utile, anche se è molto minimo.


2
In realtà non ho usato le unità Jedi JCL per accedere alle informazioni TD32 - Ho la mia libreria proprietaria per questo, ma sembra che tutto l'impianto idraulico di base di cui avrai bisogno sia lì in JclTD32.pas. Non c'è alcun codice demo che posso trovare per accedere alle informazioni sulle variabili, tuttavia, ma l'esempio che è lì (in .. \ jcl \ examples \ windows \ debug \ sourceloc) mostra come ottenere informazioni sul numero di riga dai dati TD32, quindi dovresti essere in grado di costruire su questo per ottenere ciò di cui hai bisogno. Riporta qui quello che hai scoperto :)
500 - Errore interno del server

2
@ 500-InternalServerError Grazie. Le informazioni sul numero di riga sono semplici (sono anche nei file mappa), ma puoi fornire informazioni su ciò che vedi nel codice JCL che si riferisce specificamente ai simboli locali? Inoltre, per curiosità, qual è la tua libreria proprietaria TD32 ed è pubblicata / utilizzabile pubblicamente o solo internamente?
David

3
Ogni simbolo di procedura / funzione / metodo sotto di esso contiene a sua volta un elenco di simboli ad esso locali. La maggior parte delle definizioni sembra essere presente nell'unità Jedi, ma alcune sono commentate. Il mio suggerimento sarebbe quello di creare minuscole app di test e guardare cosa restituisce un'enumerazione di simboli. Il codice che ho è proprietario e non posso pubblicarlo. Non copre comunque l'argomento delle variabili locali. Ma le informazioni su cui si basa sono semi-pubbliche, quindi potrei essere in grado di aiutarti se incontri muri specifici.
500 - Errore interno del server

4
tds2pdb ( code.google.com/p/map2dbg ) sembra avere un parser per i file tds. Tuttavia è codice C #.
Graymatter

4
C'era un documento informale, sì, ma poi Borland (all'epoca) decise di rilasciare una dll invece per accedere alle informazioni di debug in modo che potessero cambiare il formato interno e non dover aggiornare la documentazione. Sfortunatamente, al momento non riesco a trovare né il documento originale né la DLL. Ti suggerisco di contattare il supporto tecnico di Embarcadero e chiedere informazioni.
500 - Errore interno del server

Risposte:


2

Controlla se i simboli di debug non erano in binario. È anche possibile utilizzare GDB (su Windows un port di esso). Sarebbe fantastico se trovassi un file .dbg o .dSYM. Contengono codice sorgente, ad es.

gdb> list foo
56 void foo()
57 {
58  bar();
59  sighandler_t fnc = signal(SIGHUP, SIG_IGN);
60  raise(SIGHUP);
61  signal(SIGHUP, fnc);
62  baz(fnc);
63 }

Se non hai file di debug, puoi provare a ottenere MinGW o Cygwin e utilizzare nm (1) ( pagina man ). Leggerà i nomi dei simboli dal binario. Possono contenere alcuni tipi, come quelli C ++:

int abc::def::Ghi::jkl(const std::string, int, const void*)

Non dimenticare di aggiungere l' --demangleopzione o otterrai qualcosa come:

__ZN11MRasterFont21getRasterForCharacterEh

invece di:

MRasterFont::getRasterForCharacter(unsigned char)

2
Jakub, grazie per la risposta. Sfortunatamente probabilmente ho bisogno di leggere un formato di debug specifico: TDS. Le app Delphi non sono compilate con informazioni di debug compatibili con GDB su Windows. Non sono sicuro di come nm possa aiutare, dato che si baserà su uno specifico formato di file di debug che probabilmente non è quello generato da Delphi. O ho frainteso la tua risposta: GDB può leggere i simboli di Delphi, per esempio?
David

@DavidM, il tuo commento è molto cruciale. Prova a trovare il port di GNU Binutils o GNU Debugger su Windows (conosco solo il port di Binutils). C'è una libreria BFD per GDB. È usato anche in Binutils. Permette di leggere più formati di file e riconoscerli dai loro numeri magici. Se tutto fallisce, usa lo strumento chiamato strings. Estrarrà le stringhe da qualsiasi file binario. Vedere la pagina man . Questo stamperà stringhe che potrebbero ma non devono essere utili
Top Sekret

0

Dai un'occhiata al http://download.xskernel.org/docs/file%20formats/omf/borland.txt Open Architecture Handbook. È vecchio, ma forse trovi alcune informazioni rilevanti sul formato del file.


Puoi aggiungere un po 'di contesto, il collegamento potrebbe interrompersi in futuro.
Hintham,

Il collegamento contiene il documento ufficiale di Borland sul formato di file OMF utilizzato dal compilatore Borland e altri formati di file binari utilizzati da Borland. Alcuni anni fa ho esaminato il formato di file TDS e sembrava che alcune parti fossero compatibili con i formati di file documentati. Quando si tenta di raccogliere informazioni sulle variabili locali dal file TDS, è necessario utilizzare o fare riferimento alla documentazione collegata. Se il collegamento si interrompe, la mia risposta sarà inutile e le informazioni necessarie andranno perse. Il link "Open Architecture Handbook" faceva parte delle vecchie versioni Turbo Pascal e C.
Muetze1
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.