This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Goto Label xxx in other file...

Dear all,
I have a question about jumping to some specific label in other file(in Keil C51 project)

Ex. In file A there is one label named _xxx. In file B can we use

goto _xxx

?
(maybe _xxx should be declared as extern, right ?)

The reason why I want this is: We did NOT want to do the tasks before label _xxx because they are wrong...! And unfornately file A is located in ROM and we can not modify it...

So we want to just jump to label _xxx and skip wrong codes....

Parents
  • No, it wasn't an opinion, but a representation of limitations of the C goto mechanism. There is a "longjmp" functionality but that is also outside the scope of this issue.

    Assembler code can jump to anywhere in the code address space. You just have to make use of the correct absolute address which you might have picked up from listings/map files of the original ROM code.

    C code can perform a call (not jump) using a function pointer that have been set to the absolute address. But that requires that stack etc are properly setup and that your current C function perfectly matches all assumptions required at the "reception point". And that the called (not jumped) target never returns, or that it contains a code sequence that returns in a compatible way back to your C function - while still fullfilling all requirements/assumptions about used registers etc.

    My opinion is that performing "cut" and "paste" trying to reuse already existing binary code is best done from assembler where you have 100% control of every register etc before jumping into this address. The question here is if you have created a list of all requirements that needs to be fulfilled for this absolute jump to give the expected result.

    By the way - you have never mentioned if the code in ROM is compiled code from a C program or is created from hand-written assembler instructions. That makes a big difference when itemizing all requirements that needs to be fulfilled for this jump to give expected result.

Reply
  • No, it wasn't an opinion, but a representation of limitations of the C goto mechanism. There is a "longjmp" functionality but that is also outside the scope of this issue.

    Assembler code can jump to anywhere in the code address space. You just have to make use of the correct absolute address which you might have picked up from listings/map files of the original ROM code.

    C code can perform a call (not jump) using a function pointer that have been set to the absolute address. But that requires that stack etc are properly setup and that your current C function perfectly matches all assumptions required at the "reception point". And that the called (not jumped) target never returns, or that it contains a code sequence that returns in a compatible way back to your C function - while still fullfilling all requirements/assumptions about used registers etc.

    My opinion is that performing "cut" and "paste" trying to reuse already existing binary code is best done from assembler where you have 100% control of every register etc before jumping into this address. The question here is if you have created a list of all requirements that needs to be fulfilled for this absolute jump to give the expected result.

    By the way - you have never mentioned if the code in ROM is compiled code from a C program or is created from hand-written assembler instructions. That makes a big difference when itemizing all requirements that needs to be fulfilled for this jump to give expected result.

Children
  • The code in ROM is compiled code from a C program.

    And the reason why I did not use the redirection way(like Erik said) is: what I want to call is NOT a function, but a piece of code segments in ROM. Thus I can not use RalphReplace() to replace Ralph() !

    I have one idea about this issue and maybe you all can give me some opinions...

    (1) create .a51 file where .a51 contains:
    - function C()
    - The function body of C() is only "jump to the specific absolute address"(I can get it in .m51 file)
    (2) add this .a51 to my project
    (3) declare function C() as "extern"
    (4) In File B, call C()...

    Is it possible to solve this issue ?

  • .... how are you going to get back?

    Erik

  • The ROM code is part of a function.

    Functions are called - not jumped to.

    This is important, because the last part of that function wants to do a return - and then it needs a return address.

    So you must call - not jump. Or manually set up a return address.

    Next thing. That part of the already existing code expects that that there are parameters, and local variables (maybe on stack - maybe modified into global variables). Your stub function must make sure it fulfills these requirements too.

    Third - because you have a label in the assembly listing doesn't mean that you have a "clean break". That function may expect a number of values in registers (or in local or global variables). This must be matched by your stub function.

    Fourth - if the function did pass anything on stack, then it would probably assume that the caller clears the stack after the function returns.

    Fifth ...

    Do you get the idea? Knowing an address in ROM does not make it easy to jump/call to that address and get a good result. You must be very familiar with all requirements. But if you was very familiar with them, you would not have created this thread in the first place. And we can't help you, since we can't see your code. So you have a bit of a gordian knot here.
    - if you know the requirements, you don't need to ask.
    - if you need to ask, you don't have the requirements to get this to work.

    For this to work, you must be able to reverse-engineer the exact behaviour of the relevant part of the ROM code. And then make an assembly stub function that recreates the required "sandbox".

  • Thanks for all your comments first !

    Why I wanted to do so originated from the customer report issue - our firmware code failed if using downgrade product. Then We found if we can "skip" some tasks then this issue is solved.
    But unfortunately these codes are all in ROM, we can not modify it ! So my first idea is to jump to some specific address in ROM and this can skip these tasks if available...

    Assume N means "NG" code and O is "OK" code. Then N is small(in code size) and O is big(in code size) Besides, N and O are not functions,just code segments.

    Code in ROM

    void main()
    {
    // code N here
    _xxx:  // label here
    // code O here
    // code O here
    // code O here
    // ...
    
     while(1)
     {
      // polling to receive command,execute command...
     }
    
    }
    

    If we use new function to replace the O part,then it will consume much code space. Besides we want the code transfer to the while(1) part to (polling,receive,and execute requests),like the normal case...

    That is the reason why I want to try "jump" first because in this case:
    #1 no need to pass parameters and local variables
    #2 the "requirements" in this situation might be little(code N is simple)

    I will try to reverse-engineer the exact behaviour of the relevant part of the ROM code then decide the better way...

    Thanks !

    liaoo

  • But unfortunately these codes are all in ROM, we can not modify it !

    How then will you then implement your "jump" change? I don't understand.

  • If you do what you intend to do, you will cause more damage than anything else. Ignoring calling convention, stack load etc. will get in into deadly trouble. Don't do it. Work on the software, change it and fix it. And above all: UNDERSTAND WHAT THE PROBLEM IS BEFORE STARTING!

  • How do y our program get started? You can't circumvent the bad part of early main() unless something before main() calls your new code stored somewhere else.

    But yes - if you do reverse-engineer the bad section, then you can basically copy that instruction sequence into an assembler file. Modify to correct for bugs. Then perform a jump to the absolute address where the good code continues.

    Just note that there may be a bit of overlapping between good/bad because the compiler optimization may have changed order of instructions.

    This concept only works if you have the skill to:
    - duplicate the route into main()
    - finds a suitable target spot to jump to, where you have managed to lock down all assumtions made by the compiler for the following code. You need to understand exactly what happens earlier. And you need to know a bit about the following code too.
    - duplicate any required registers, local and global variables the "good" code expects to have been assigned.

    You can normally not do this in C, because you can't instruct the compiler to produce the exact conditions you need. You can - if you have the same compiler - write the code fix in C, to look at the generated instructions. But the bandage needs to be applied using assembler.

    Patchning code like this have been done a number of times. The only two requirements are:
    - the skills to understand exactly what happens and what is needed.
    - a means to "steal" the execution. On a PC, programs are run in RAM so it's trivial to patch in a jump/call at start of the bad code or befure the bad code is about to be executed. With a microcontroller with the code in flash - and autostarting - it is very much trickier. All the way up to impossible depending on chip and code design.

  • Per,

    What you described is Stuxnet stuff :-)