Question about C

W

William Hughes

jacob said:
#include <math.h>
#include <stdio.h>
static int fn(int s)
{
         if (s > 0)
             return sqrt(s)/pow(s,3);
         else return pow(s,3);
}
int main(void)
{
         int (*fptr)(int) = fn;
         char *p = (char *)fptr;
         printf("First 10 bytes of the opcodes of fn are:\n"); for (int
         i = 0; i<10;i++) {
                 printf("[%d] %d 0x%x\n",i,p,p);
         }
}

Hello jacob ~~
You probably know it, but that code will NOT work on a platform where C
is interpreted not compiled. Also a static function could be completely
removed by the compiler since it is not externally visible, then you
would get the first opcodes of main().
Regards ~~

How about a version of C in which you could get and change both source
and object code at all times?

You can get both in .Net, and you can call the compiler which means
you can change both. In principle (I haven't figured out myself how to
do it).

So much for C's "power".

Hmm...taking Herb Schildt's old C interpreter...porting it
to .Net...adding this ability...nyhah ha haaah


Well, there are many implementations where you can access and
modify the executable image. However, a mandate that all
implementations have this capability would put a large burden
on implementations for certain achitechtures (e.g. one in
which the code is in an unreadable segement) which would in
practice mean that this feature of C would not be implemented
for those architectures.

We could (noting that things are very machine specific in any
case) have a function like

get_fuction_opcodes(func, &uint_ptr, &length)

Which would return a pointer to a vector of opcodes, and the
length, or NULL, if this could not be reasonably done, and
a length of -1, if the length was not available.

However, like *any* change to the standard, this has non-trivial
cost, nor is it clear that the functionality produced is really
desirable.

- William Hughes
 
S

Stargazer

Hi, I am not a student at IUT, but I do have two questions.

Can a C programmer by means of hacking get access to the machine code
of a function? I've never used the feature by means of which a
function may be passed as its address, but it sounds like one could
use this (in real programming, don't pass functions: write a small
interpreter).

Shouldn't C be redesigned so as to make the machine code of a program
a full object, one that can be addressed and used, possibly changed? I
mean, you can mung everything else in this language. Why not be Mung
the Merciless?

int a()
{
printf("%s\n", a);

}

There's a more standard solution to this than the one being discussed,
but it requires more work. You can use argv[0] from arguments to
main(), which should hold path to your program (on systems that can
supply it). Try to fopen() it, if you succeed then good chances are
that you've opened your executable file. Parse symbol table, find your
function of interest and you can get access to it. That's actually
what a debugger or tool like objdump would do.

Modification is harder - on some systems code sections/segments are
not even readable (execute-only) and virtually on all (except small
unprotected RTOS) they are non-writable. Some OS would allow you remap
code in your address space as writable - consult documentation for
OSes that you intend to run on.

Daniel
 
M

Michael Tiomkin

Well, I recall that on some machines
(surely on AIX, but I think it's also true for Windows and other
Unixes), when calling a function from a DLL or system library, there
is a need to save/restore the data registers etc., so a call goes to
an intermediate chunk that does exactly this.

In addition, if you really want to see your precious function, just
open it's
address in a debugger, and ask to disassemble.


Hi, I am not a student at IUT, but I do have two questions.
Can a C programmer by means of hacking get access to the machine code
of a function? I've never used the feature by means of which a
function may be passed as its address, but it sounds like one could
use this (in real programming, don't pass functions: write a small
interpreter).
Shouldn't C be redesigned so as to make the machine code of a program
a full object, one that can be addressed and used, possibly changed? I
mean, you can mung everything else in this language. Why not be Mung
the Merciless?
int a()
{
printf("%s\n", a);

There's a more standard solution to this than the one being discussed,
but it requires more work. You can use argv[0] from arguments to
main(), which should hold path to your program (on systems that can
supply it). Try to fopen() it, if you succeed then good chances are
that you've opened your executable file. Parse symbol table, find your
function of interest and you can get access to it. That's actually
what a debugger or tool like objdump would do.

Modification is harder - on some systems code sections/segments are
not even readable (execute-only) and virtually on all (except small
unprotected RTOS) they are non-writable. Some OS would allow you remap
code in your address space as writable - consult documentation for
OSes that you intend to run on.

Daniel
 
L

lawrence.jones

Stargazer said:
There's a more standard solution to this than the one being discussed,
but it requires more work. You can use argv[0] from arguments to
main(), which should hold path to your program (on systems that can
supply it).

No, argv[0] contains the *name* of the program, which is usually *not*
the complete path and might not have anything whatsoever to do with the
path to the executable file.
 
M

Malcolm McLean

No, argv[0] contains the *name* of the program, which is usually *not*
the complete path and might not have anything whatsoever to do with the
path to the executable file.
You need to look at the environment pointer, passed in as a third
parameter, which usually contains the paths to directories containing
executables. However that's also non-ANSI, of course.
 
B

Ben Bacarisse

Malcolm McLean said:
No, argv[0] contains the *name* of the program, which is usually *not*
the complete path and might not have anything whatsoever to do with the
path to the executable file.
You need to look at the environment pointer, passed in as a third
parameter, which usually contains the paths to directories containing
executables. However that's also non-ANSI, of course.

That's rather old-fashioned advice: standard C has getenv. Why use
anything else?

If you must, POSIX[1] requires that the environment be accessible via

extern char **environ;

It's a few years since I've seen code that uses a third parameter to
main to do this.

[For what it's worth, even combining argv[0] with some component of the
PATH environment variable will not always solve the problem.]

[1] I use the term as a shorthand.
 
W

William Hughes

No, argv[0] contains the *name* of the program, which is usually *not*
the complete path and might not have anything whatsoever to do with the
path to the executable file.

You need to look at the environment pointer, passed in as a third
parameter, which usually contains the paths to directories containing
executables. However that's also non-ANSI, of course.


Well, if there is anything in the environment that will help
you have getenv(). Of course there are no guarantees, and even
if you can find the executable there are no guarantees that you
can open it, or even that it contains anything useful.

- William Hughes
 
S

Seebs

That's rather old-fashioned advice: standard C has getenv. Why use
anything else?

Consider asking the question "what values are in the environment?"

With getenv(), this requires a search of an extremely large space.

-s
 
K

Keith Thompson

Seebs said:
Consider asking the question "what values are in the environment?"

Which is a different question.
With getenv(), this requires a search of an extremely large space.

But if the question is "what is the current value of $PATH", getenv is
just the thing.
 
B

Ben Bacarisse

Seebs said:
Consider asking the question "what values are in the environment?"

That's true, but I was not asking "why use anything else" in general, I
was asking "why use anything else to do what Malcolm seemed to be
suggesting". I must turn my c.l.c "make sure every statement stands
alone with no context" parser back on. :)

Of course he might have been suggesting scanning the whole environment
but that seems like a rather reckless way to find an executable file.

<snip>
 
R

Richard Bos

Malcolm McLean said:
No, argv[0] contains the *name* of the program, which is usually *not*
the complete path and might not have anything whatsoever to do with the
path to the executable file.

Not even that; it _represents_ the program name. If the program has been
called in an unusual way (or on an unusual OS), it might not even have
anything to do with the real name of the executable file.
You need to look at the environment pointer, passed in as a third
parameter, which usually contains the paths to directories containing
executables. However that's also non-ANSI, of course.

....and, partly because of the above, does not work in the general case.

And then, even with a perfectly normal program execution, who is to say
that running "\not\in\the\normal\executable\PATH\environment\progname"
does not result in argv[0] containing only "progname"? If PATH contains
"\$HOME$\programs;\public\programs;\\progserver\\public\programs" and
there happens to be another program, also called "progname", on that
server referred to in that PATH, your method will find the wrong program
file. And that's not a _very_ unlikely scenario, you'll have to admit.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,093
Messages
2,570,610
Members
47,230
Latest member
RenaldoDut

Latest Threads

Top