; --------------------------------------------------------------------------------
; @Title: Script to debug a uClinux process from the start (Linux-3.x Awareness)
; @Description:
; Application Debugging (AutoLoader version)
;
; This script waits for an application to be started,
; loads the symbols and halts the application at main()
;
; NOTE: uClinux and the uClinux awareness must be up.
;
; start this script with the process name as argument
; e.g.: do app_debug hello
;
; Prerequisites:
; - Linux must be booted
; - Linux awareness must be configured
; - Autoloader must be configured
;
; @Keywords: uClinux process awareness
; @Author: DIE
; @Copyright: (C) 1989-2017 Lauterbach GmbH, licensed for use with TRACE32(R) only
; --------------------------------------------------------------------------------
; $Id: app_debug_uclinux.cmm 2512 2017-10-03 13:43:03Z kjmal $  

 ; define local macros
 LOCAL &process &breakaddr &codeaddr &dataaddr
 
; get the process name as parameter to the script
 ENTRY &process


 ; Activate autoloader for processes:
 TASK.sYmbol.Option AutoLoad Process
 

; Delete possibly existing breakpoints of previous process runs
 
 IF sYmbol.EXIST("\\&process")
   Break.Delete sYmbol.SECRANGE(\\&process\.text)


; Wait for process to be loaded.
; The process must be started by executing it in the uCLinux console.

 // we cannot load process symbols as long as we don't know
 // the code and data addresses. Those are set up for the 
 // new process, right before it is started at set_binfmt()

 IF STATE.RUN()
    Break.direct    ; halt target for breakpoint setting

 ; set_binfmt() is called for every process to start -
 ; the conditional breakpoint halts only, if the process
 ; is found in the process table.

 &breakaddr=ADDRESS.OFFSET(set_binfmt)
 Break.Delete &breakaddr    ; delete previous set breakpoints
 Break.Set &breakaddr /CONDition (task.proc.codeaddr("&process")&0xFFFFFFFF)!=0xFFFFFFFF

 ON PBREAKAT &breakaddr GOTO continue1    ; if breakpoint reached: continue
 Go.direct         ; let the target run and load the process
 PRINT "waiting for &process to be started..."

 STOP       ; halt script until breakpoint reached

 ; breakpoint hit, continue script
continue1:

 Break.Delete &breakaddr
 ON PBREAKAT &breakaddr     // delete script action
 

 ; Yep! The process is loaded and we found it.
 
 ; Now load the process symbols (relocated)

 PRINT "process &process started, loading symbols..."

 sYmbol.AutoLOAD.CLEAR "&process"   ; clear possibly previous set
 sYmbol.AutoLOAD.CHECK              ; force new autoloader list
 sYmbol.AutoLOAD.TOUCH "&process"   ; force loading of process symbols
 
// Now set a breakpoint at it's main entry point.
 
 // There may be more "main" symbols in the system,
 // we're searching for the right one.
 
 Eval 0
 sYmbol.ForEach "Eval address.offset(*)" \\&process\*\main
 &breakaddr=EVAL()

 IF &breakaddr==0
 (
   PRINT "symbol 'main' of process &process not found"
   ENDDO
 )

 Break.Set &breakaddr       ; set breakpoint on main

 ON PBREAKAT &breakaddr GOTO continue2  ; if breakpoint reached: continue
 Go.direct         ; let the target run and start the process
 PRINT "waiting for reaching main..."

 STOP       ; halt script until breakpoint reached

 ; breakpoint hit, continue script
continue2: 
         
 Break.Delete &breakaddr    // delete breakpoint
 ON PBREAKAT &breakaddr     // delete script action


 PRINT "done."
 
; NOTE: if finished debugging with a process, or if restarting
 ; the process, you have to delete the symbols and restart the
 ; application debugging. Delete the symbols with
 ; sYmbol.AutoLoad.CLEAR "&process"


 ENDDO
