Title: MED17 How to find maps? Post by: Sagishm on August 22, 2021, 02:31:41 AM Hi All,
i tried to learn how to disassemble MED17, i tried to read in FR and some docs about Infineon chip. i have a question about finding maps, there is logic like ME7.5? for example in ME7. you can find the map by: page * 4000 + value (204 * 4000 + 2256) so i try with Ghidra and i found this section: LAB_00108592 XREF[1]: 0010857a(j) 00108592 37 01 68 f0 extr.u d15,d1,#0x0,#0x8 00108596 37 04 70 40 extr.u d4,d4,#0x0,#0x10 0010859a 13 af 24 f8 madd d15,d8,d15,#0x4a 0010859e 60 ff mov.a a15,d15 001085a0 d9 f4 46 60 lea a4,[a15]0x586 it looks like reference to a data map but i cant understand how to calculate the location, someone can give some information about that? Thanks Title: Re: MED17 How to find maps? Post by: Sagishm on August 25, 2021, 12:50:47 AM someone can help? also reference to information will be good, thanks.
Title: Re: MED17 How to find maps? Post by: kuebk on August 25, 2021, 03:18:50 AM http://nefariousmotorsports.com/forum/index.php?topic=6990.0title=
Title: Re: MED17 How to find maps? Post by: Herleybob on September 19, 2021, 12:02:54 PM 00108592 37 01 68 f0 extr.u d15,d1,#0x0,#0x8 00108596 37 04 70 40 extr.u d4,d4,#0x0,#0x10 0010859a 13 af 24 f8 madd d15,d8,d15,#0x4a 0010859e 60 ff mov.a a15,d15 001085a0 d9 f4 46 60 lea a4,[a15]0x586 First you need to go to the xref and determine what the value of d1. Once you determine that, take the first 8 bytes, then multiply it by 0x4a. Then you need to determine what d8 is (in the xref) then add them together. Then it will move the address/offset into the register a15. You then need to determine the value of a4. once you have that, add 0x586 to the value in a15 you previously calculated and then add that value to a4 and that will take you to the address you are looking for. Edit: can i get the bin you are working on and any known ram addresses and i can help. Title: Re: MED17 How to find maps? Post by: Sagishm on January 31, 2022, 12:32:22 AM First you need to go to the xref and determine what the value of d1. Once you determine that, take the first 8 bytes, then multiply it by 0x4a. Then you need to determine what d8 is (in the xref) then add them together. Then it will move the address/offset into the register a15. You then need to determine the value of a4. once you have that, add 0x586 to the value in a15 you previously calculated and then add that value to a4 and that will take you to the address you are looking for. Edit: can i get the bin you are working on and any known ram addresses and i can help. Hi, i attached the file. basicly i think: d1 = refrance to d0002298 - so what the logics there ? d0002298 * 4a? looks like not correct. d8 = d8,[a9]LAB_00000660 a9 = i can't find that refrance, maybe i miss something in Ghidra. Thanks Title: Re: MED17 How to find maps? Post by: prj on February 01, 2022, 02:21:05 AM I mean yeah, reversing MED17 is a little more than pressing "X" button.
Maps are accessed through a double pointer dereference and an offset. It is possible to set up Ghidra, so it actually tracks the whole path nicely... Title: Re: MED17 How to find maps? Post by: Sagishm on February 04, 2022, 12:04:22 PM I mean yeah, reversing MED17 is a little more than pressing "X" button. Thanks you for response.Maps are accessed through a double pointer dereference and an offset. It is possible to set up Ghidra, so it actually tracks the whole path nicely... I know there is double pointer, i tried to find the table start area without knowing some of code, basically of my question i found that by reverse the ldrxn location but for me its not enough good. Maybe i did not set the Ghidra properly, there is something special needs to do or just to load file with specific processor is enough? Thanks Title: Re: MED17 How to find maps? Post by: prj on February 04, 2022, 01:41:51 PM With some simple analysis of binary you can find where a9 points to. If you look in this subforum, this was already talked about long ago.
You reached the limit of what the tools will do for you automatically, now at least some skill is required to set the global registers correctly... better read the TriCore EABI. Title: Re: MED17 How to find maps? Post by: terminator on February 04, 2022, 01:47:55 PM I think you do not clearly understand how Tricore works. I recommend you to read a user manual first.
Global registers (d0, d1, a8, a9) contain something like constants (they can't be quickly changed) and usually a9 points to the table(map) that contains offsets. madd d15,d8,d15,#0x4a // I believe d8 contains an offset of the map(74 x Rows), d15 is a line number mov.a a15,d15 lea a4,[a15]0x586 And disassembly is not an easy way to find maps. Title: Re: MED17 How to find maps? Post by: Sagishm on February 05, 2022, 05:36:26 AM I know is not easy, but both you are right, someone can share the Tricore manual?
Thanks Title: Re: MED17 How to find maps? Post by: prj on February 05, 2022, 05:48:00 AM Google didn't help you?
Title: Re: MED17 How to find maps? Post by: prj on February 05, 2022, 05:48:48 AM I think you do not clearly understand how Tricore works. I recommend you to read a user manual first. d0 and d1 are not global registers on TriCoreGlobal registers (d0, d1, a8, a9) contain something like constants (they can't be quickly changed) and usually a9 points to the table(map) that contains offsets. madd d15,d8,d15,#0x4a // I believe d8 contains an offset of the map(74 x Rows), d15 is a line number mov.a a15,d15 lea a4,[a15]0x586 And disassembly is not an easy way to find maps. Title: Re: MED17 How to find maps? Post by: terminator on February 05, 2022, 02:13:02 PM a0 a1 of course)
Title: Re: MED17 How to find maps? Post by: 360trev on February 05, 2022, 05:05:52 PM a0 a1 of course) Well not just... On the entry of the MED17 code the developers defined this common code on the entry point of the code, early on in the bootstrapping. bear in mind it can vary a little bit in terms of the optional a8 and a9 but this is a good signature search to find to isolate the setup on pretty much any MED17 binary that I downloaded and tried it on. _main+0 4D 40 E0 0F mfcr d0, #0xFE04 _main+4 8F 00 50 F1 or32 d15, d0, #0x100 _main+8 CD 4F E0 0F mtcr #0xFE04, d15 _main+C 0D 00 C0 04 isync _main+10 91 10 00 0D movh.a a0, #@HIS(_SMALL_DATA_) _main+14 D9 00 80 8A lea a0, [a0]@LOS(_SMALL_DATA_) _main+18 91 90 00 18 movh.a a1, #@HIS(_SMALL_DATA2_) _main+1C D9 11 20 FD lea a1, [a1]@LOS(_SMALL_DATA2_) _main+20 91 10 00 8C movh.a a8, #@HIS(_SMALL_DATA3_) _main+24 D9 88 20 E8 lea a8, [a8]@LOS(_SMALL_DATA3_) _main+28 A0 09 mov16.a a9, #0 _main+2A CD 40 E0 0F mtcr #0xFE04, d0 _main+2E 0D 00 C0 04 isync Let's walk though this a bit further... _main: //---------------------------------------------------------------------------------------------------------- /* * uint32 PswTemp_u32 = __mfcr($PSW); // save PSW * __mtcr($PSW, (PswTemp_u32 | (1 << CSFR_PSW_GW_POS))); // set bit GW * * _isync(); // ISYNC */ 0x80123224: 4d 40 e0 0F mfcr d0 ,#0xfe04 0x80123228: 8f 00 50 F1 or d15 ,d0 ,#0x100 // Init CSFR PSW, with addition of GW bit being set 0x8012322c: cd 4f e0 0F mtcr #0xfe04 ,d15 0x80123230: 0d 00 c0 04 isync So yes, A0 is a global... //---------------------------------------------------------------------------------------------------------- /* * asm volatile ("movh.a %a0, HI: _SMALL_DATA_ "); // Set global register A0 * asm volatile ("lea %a0,[%a0] LO: _SMALL_DATA_ "); */ 0x80123234: 91 10 00 0D movh.a a0 ,#0xd001 0x80123238: d9 00 80 8a lea a0 ,[a0 ]-0x5600 // _SMALL_DATA1 = 0xD0015600 //---------------------------------------------------------------------------------------------------------- And so is A1... /* * asm volatile ("movh.a %a1, HI: _SMALL_DATA2_ "); // Set global register A1 * asm volatile ("lea %a1,[%a1] LO: _SMALL_DATA2_ "); */ 0x8012323c: 91 90 00 18 movh.a a1 ,#0x8009 0x80123240: d9 11 20 fd lea a1 ,[a1 ]-0x2c20 // _SMALL_DATA2 = 0x80092C20 //---------------------------------------------------------------------------------------------------------- On some implementations A8 is defined as a global too (or zero)... /* * asm volatile ("mov.a %a8, 0 "); // Set global register A8 to 0 * * // or * * asm volatile ("movh.a %a8, HI: _SMALL_DATA3_ "); // Set global register A8 * asm volatile ("lea %a1,[%a8] LO: _SMALL_DATA3_ "); */ 0x80123244: 91 10 00 8c movh.a a8 ,#0xc001 0x80123248: d9 88 20 e8 lea a8 ,[a8 ]-0x7c60 // _SMALL_DATA3 = 0xC0017C60 //---------------------------------------------------------------------------------------------------------- And even A9.. In this case its defined as Zero /* * asm volatile ("mov.a %a9, 0 "); // Set global register A9 to zero */ 0x8012324c: a0 09 mov.a a9 ,#0x0 0x8012324e: cd 40 e0 0f mtcr #0xfe04 ,d0 /* * _isync(); // ISYNC */ 0x80123252: 0d 00 c0 04 isync //---------------------------------------------------------------------------------------------------------- Furthermore its very common to see this kind of access on MED17. This is obviously dependent on the code generation of the GCC itself. It technically doesn't have to be like that but this gives you some idea. Now that the GCC 4.9.2 binaries and source-code are available freely there is literally no excuse not to play around with code generation and bintools to see how C code is translated into tricore assembly... This approach will rapidly accelerate your learning. ; Source File : 'E_ACTIVATETASK.c' extrn os_i_lsIntMask extrn os_i_mon_Ptr extrn os_suspend_interrupts extrn os_i_fifoSize_Ptr extrn os_i_taskFifoPtr_Ptr extrn os_resume_interrupts extrn GetSystemTimeLow extrn os_ServiceId extrn OSErrorUnion extrn os_error extrn os_i_nofCoopLvls extrn os_maxSwPreempPrio extrn os_ceilingPrio extrn os_i_schedIntCtrlTab_Ptr extrn SC_INT_ADR extrn os_nextCoopPrio 82 1F mov16 d15, #1 91 xx xx F0 movh.a a15, #@HIS(os_osek_task) D9 FF 01 10 lea a15, [a15]@LOS(os_osek_task) 28 0F st16.b [a15]0, d15 ; os_osek_task os_osek_task = 1; 91 xx xx C0 movh.a a12, #@HIS(os_ercosekSP) D9 CC 04 10 lea a12, [a12]@LOS(os_ercosekSP) D4 CD ld16.a a13, [a12] ; a13 = os_ercosekSP 80 D4 mov16.d d4, a13 ; d4 = a13 (copy of os_ercosekSP) A0 4E mov16.a a14, #4 ; a14 = 4 01 ED 20 D0 sub32.a a13, a13, a14 ; a13 =- a14; (ie subtract 4 from os_ercosekSP) F4 CD st16.a [a12], a13 os_ercosekSP -= 4; 91 xx xx F0 movh.a a15, #@HIS(os_switchToStartupStack) D9 FF 08 10 lea a15, [a15]@LOS(os_switchToStartupStack) 2D 0F xx xx calli a15 fp = (FP)os_switchToStartupStack; fp(); 00 90 ret16 Title: Re: MED17 How to find maps? Post by: prj on February 06, 2022, 03:35:28 AM @Trev, it is enough to read the TriCore EABI.
Quote 2.2.1.4 System Global Registers Address registers A[0], A[1], A[8], and A[9] are designated as system global registers. They are not part of either context partition and are not saved/restored across calls. They can be protected against write access by user applications. Sometimes a good old dose of RTFM is a good idea. Use the brain cells reversing where you actually need to reverse, not reversing what is laid out in the EABI. Furthermore: Quote By convention, A[0] and A[1] are reserved for compiler use, while A[8] and A[9] are reserved for OS or application use. A[0] is intended as a base pointer to the “small” data section, where global data elements can be accessed using base + offset addressing. It is part of the execution environment and will always be initialized in the startup code for any EABI-compliant RTOS. A[1] is intended as a base pointer to the “literal data section”. The literal data section is a read-only data section intended for holding address constants and program literal values. Like A[0], it is initialized in the startup code for any EABI-compliant RTOS. (See Special Sections, page 4-4, for further information.) As noted, A[8] and A[9] are reserved for OS use, or for application use in cases where the application and OS are tightly coupled. The compiler may support a directive that allows a global pointer variable to be bound to one of these registers. In the absence of such a directive the registers can only be used from assembly coded functions. A typical OS use would be as a pointer to the current task control block, or to the task ready queue, for reducing executive overhead in task management functions. All that remains to do is find where they are assigned (as in your post), and set them. |