Reading power PC MPC 8260 program counter (Next Instruction address)

Hello, Please can somebody let me know how to read power PC 8260 program counter using C program (Using asm directive). Thanks, Rajesh

Reply to
rajesha
Loading thread data ...

That seems to me to be a "fools errand". By the time you've read the program counter, the program counter has changed. Each instruction executed changes the program counter, and in a multi-processing architecture like Linux, each context switch changes the program counter as well. By the time your code has retrieved the counter, the counter has changed.

Anyway, it's a trivial thing to get the PC (or reasonable facsimile) in C code:

void dummy(void) { void (*pc)() = &dummy; /* got the PC on entry to the function */ /* ... */ }

--
Lew Pitcher
Master Codewright & JOAT-in-training   | Registered Linux User #112576
Me: http://pitcher.digitalfreehold.ca/ | Just Linux: http://justlinux.ca/
----------      Slackware - Because I know what I'm doing.         ------
Reply to
Lew Pitcher

I've had occasion to want to read the current PC from within a program. I've used it as a simple way to distinguish between running from flash after startup, or running from ram via a debugger. I'm sure there are other uses too, perhaps involving debugging or testing, or diagnostic outputs on error.

Reply to
David Brown

z.>

counter

ogram

nges

ur

C
*/
h

I see. You really don't care about the program counter; you just want to know where your program was loaded.

So, the above code sample should be all you need for that. Just test the value of to see if it fits within the range of addresses that map to flash or the range of addresses that map to ram.

HTH

-- Lew Pitcher Master Codewright and JOAT-in-training

Reply to
Lew Pitcher

The compiler may complain: The function name is a pointer to the first instruction without the address operator (&).

void (*pc)() = dummy;

--

Tauno Voipio
tauno voipio (at) iki fi
Reply to
Tauno Voipio

xyz.>

m counter

program

hanges

x,

your

in C

n */

ash

e

FWIW, it would be better to just look at the contents of /proc// maps for the pid of the process in question. That'll show you exactly where each loadable element of your process is placed in memory.

Reply to
Lew Pitcher

I can't speak for the OP, but for my own use (which was not on a PPC, so I don't have direct code), I needed to know where the code was running from at the time. However, your code would not have helped me - it returns the logical address that the linker uses for when the program is running. But when starting up (without a debugger), my program only existed as a copy in flash - the real run-time copy of the program was linked to run from ram, and needed to be copied over. So if I took the address of the "dummy" function, it would give the address in ram - I needed the real PC (or at least, I needed to determine the higher bits of the real PC). It is not even safe to call a function directly at this stage - it would have to be done using a function pointer and some bit masking of the address.

So for my use, the processor's "LEA" instruction was the most convenient correct method. Other possibilities include using a safe function call (either using a corrected function pointer, or a relatively address function call if the processor supports it) and gcc's "__builtin_return_address" function.

Reply to
David Brown

counter

Ops, I hadn't noticed that this is comp.os.linux.embedded - I had assumed I was still in comp.arch.embedded. My system was bare-bones. Sorry for any confusion.

Reply to
David Brown

Perhaps I'm being rather naive about the situation but unless you're trying to get the address after memory mapping and/or virtual memory translation, won't &(main) give the address of main(), enough to determine if it's in RAM or ROM in an embedded system?

Profiling system calls & libraries such as profil(3) give indirect access to the program counter.

Try as I might, I don't see a way to access the program counter even via a signal handler since the return address is on the stack-frame which is not usually accessible (but can be via stack-variable tricks).

Reply to
Jeff Jonas

As I noted in another post, I was working with a bare-bones system - no OS, no virtual memory translation, no system calls. Think of it as the initial bootup from flash straight after power-on.

At that stage, it is quite possible for the hardware address of the program, thus the PC value, to be different from the logical link address of symbols like "main". Of course, this means you can't just call a function like main() - the processor will jump to an invalid address. This is the time when the code has to handle things like copying the code from flash into ram (if that's appropriate for the system), clearing the bss, initialising the data section, and so on - before main() starts.

It's not something you normally deal with in programming - it is handled by the OS or by the compiler and library startup code. In normal circumstances, you are of course correct - taking the address &main is typically all you need.

Reply to
David Brown

I know this problem, but I think it is not handled properly this way. If you want code to run at address x, compile and link it to address x. If you have to move code around, make a separation between the mover and the movee. The movee has correctly linked addresses as per the above. Then this kind of problem goes away.

Of course modern "user friendly" IDE's kan make this switching of view from data to code extremely difficult for lack of transparancy.

Groetjes Albert

--

--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
Reply to
Albert van der Horst

In C, the name of a function is a constant pointer to the function (without the address operator &):

int main() { ; }

then

main

is a pointer to an int function without specified arguments.

The expression &main and &(main) should get complaints from the compiler.

The pointer is existing in the compiled code without any library or operating system support required.

--

Tauno Voipio
tauno voipio (at) iki fi
Reply to
Tauno Voipio

True.

False. The '&' is redundant, but it is allowed. To my mind it is clearer to use it than to omit it, as one more indication that the intent is not to call the function but to take its address.

Quoting from the C99 standard:

6.5.3.2 Address and indirection operators

Constraints

1 The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

Note the case of "a function designator".

For a statically linked program the address &foo is a link-time constant that shows where the linker placed foo, which is where the linker expects foo to lie at execution time. As other posts in this thread have explained, if the code is in fact loaded or copied to another address and is sufficiently position-independent, the actual address at execution time may be different. To get the real address, you must read the actual Program Counter in some way.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .
Reply to
Niklas Holsti

That's all fine once your code is in place and executing at the right place in the right way. An example of moving code around is if you want the program to run mainly from flash, but some parts should run from ram (for example, code to re-program the flash). Then, as you say, the correct way is to make a separation so that the linker uses the correct addresses (typically you use an __attribute__((section)) specifier for the functions in question).

However, at power-on reset, code may not be running from the correct place. At that point, the processor is running the code, and any relative addressing will work correctly, but absolute addressing will be wrong. Taking the address of a function using standard C operators will give you the logical address which will be valid later on, but is invalid at this stage.

Reply to
David Brown

If it's properly position-independent, when you take the address of a symbol you'll get the place where it currently exists (e.g. the compiler will use a PC-relative address, or the data or instructions will have had relocations applied before entering C code). Otherwise lots of stuff will break. It's possible in some situations to still write C code (very carefully) that functions in such an environment, but that's a last resort for dealing with weird situations.

-Scott

Reply to
Scott Wood

Here's a straightforward answer to your question, ignoring questions about why you want to do this, if you don't trust the compiler/linker's notion of the address you're running at (assuming GCC):

asm("bl 1f; 1: mflr %0" : "=r" (addr) : : "lr");

addr now contains the address of the mflr instruction.

-Scott

Reply to
Scott Wood

If the compiler, linker, and start-up code intentionally support position-independent loading and execution, they will of course arrange for &foo to work even if the actual load and execution address is variable. This can be done by computing &foo as the run-time address of foo, as you say, but in principle a compiler could instead represent function pointers as static offsets to some "program base register", not as the full address. The run-time base address would be added when the function pointer is used in a call. The difference would be invisible to the C programmer unless the programmer inspects the numeric value of a function pointer.

I agree, but I thought we were discussing such a weird scenario, with code being manually copied from flash to RAM so that the current location of the code is not what the compiler and linker expected.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .
Reply to
Niklas Holsti

Be careful that this will lose whatever was in lr before these instructions. That is unlikely to be a problem in situations where this sort of code is necessary - you probably only need it at a stage in booting when normal function calls are not yet possible.

Reply to
David Brown

No problem, he's telling to the compiler with the last "lr" that he's clobbering the link register contents.

--

Tauno Voipio
tauno voipio (at) iki fi
Reply to
Tauno Voipio

My point was just to investigate options for proper runtime relocation first. :-)

U-Boot (at least on PowerPC) handles this by linking at the flash address, and when relocating to RAM, it process a list of relocations that the linker generated, before entering C code in the new image location.

-Scott

Reply to
Scott Wood

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.