Page 1 of 3

single function with multiple names

Posted: Sat Aug 14, 2004 3:46 am
by Candy-lazy
Is it possible in C/C++ to create a function with more than one function name? I was wondering...

I'm now at the point of making my API (thinking while helping my sister with her house). I just thought up the killt / killp combo for C, where these could both be called kill in c++ (with a different argument, one of which would probably be signed to work along with name mangling). For the C++ people this is a lot more useful, but since C programs can also be compiled with a C++ compiler, the c++ compiler must both know kill(pid_t) and killp(pid_t). They are 100% the same, so if they could both end up in the object file pointing to the same address, all would be fine. I know I can craft an object file which works like that.

How do I craft it properly with C and C++? My guess would be:

Code: Select all

#ifdef __CPLUSPLUS
void std::kill(pid_t process)
extern C {
#endif
void killp(pid_t process) {
....
}
#ifdef __CPLUSPLUS
}
#endif
but because of the extern C I have my doubts about this working. Second guess would be

Code: Select all

#ifdef CPLUSPLUS
void __ZN3std4killEt(pid_t process)
#endif
void killp(pid_t process) {
...
}
but for one this is very ugly (manual mangling isn't cool) and for two this is not portable. It even mightn't work. I have no C compiler at hand, so I'm going to have to wait until tomorrow somewhere.

Hope you can help, Candy

Re:single function with multiple names

Posted: Sat Aug 14, 2004 3:48 am
by Candy-Lazy
I want to edit!

Code: Select all

#ifdef __CPLUSPLUS
namespace std {
void kill(pid_t process)
};
extern C {
#endif
void killp(pid_t process)
}
{
....
}
#ifdef __CPLUSPLUS
}
#endif

Re:single function with multiple names

Posted: Sat Aug 14, 2004 10:04 am
by Candy
think I'm going to use

Code: Select all

#ifdef __CPLUSPLUS
inline void kill(pid_t p) {
    killp(p);
}

inline void kill(tid_t t) {
    killt(t);
}

extern "C" {
#endif
killt(tid_t t) {
...
}

killp(pid_t p) {
...
}
#ifdef __CPLUSPLUS
}
#endif
allowing both c++ usage with both names (and calling conventions), and c usage with only specific names.

Note, I'm still looking for a way to make it one function, but this is a patch method that probably allows me to skip making that stuff. I've also considered creating a program that reads an ELF file and adds a given symbol, pointing it at a given other symbol, effectively duplicating it.

Does anybody know a way in C/C++ code to do this?

Re:single function with multiple names

Posted: Sun Aug 15, 2004 12:29 am
by Dreamsmith
Traditionally in C, multiple names refering to the same function are accomplished by using #define preprocessor macros. You'll find your standard headers laced with these kinds of things in most environments. It's ugly as heck, but it works.

A more modern approach would be to use inline wrapper functions.

Re:single function with multiple names

Posted: Sun Aug 15, 2004 3:25 am
by Candy
OK, thanks, didn't know that. I was afraid it'd wreck the code structure etc., don't completely trust #define's myself. Inlines aren't inlined on -O0 so that wasn't the best option either.

Re:single function with multiple names

Posted: Sun Aug 15, 2004 9:15 am
by Dreamsmith
Actually, if you're willing to resort to some GCC-isms, the latest GCC includes an attribute to get around that:

Code: Select all

inline void foo(int x) __attribute__ ((always_inline))
Functions declared this way should be inlined regardless of the -O setting. Just to be sure, add "-Winline" to your CFLAGS to warn any time a function declared inline isn't inlined.

Re:single function with multiple names

Posted: Sun Aug 15, 2004 2:06 pm
by Candy
Dreamsmith wrote: Just to be sure, add "-Winline" to your CFLAGS to warn any time a function declared inline isn't inlined.
these defines are for the userspace section, so -Winline is not at my control :)

By the way, have decided to transform them all to pure defines. How do I make a define with an asm statement and a return value?

something like:

Code: Select all

if ((fork()) == 0) {
where fork is something like

Code: Select all

#define fork() (pid_t p; asm("syscall":"a"(SYS_FORK): "a"(p): "eax"); p)
but this one doesn't work. Something that I tried to test the syntax like:

Code: Select all

#define fake_fork() (1, 2, 3)
did work. The above statement can't work with comma's, that'd make them all space reservations for pid_t's. Using that with the pid_t declaration moved away (so the comma's can be placed) results in an error "before "asm"".

anybody?

Re:single function with multiple names

Posted: Sun Aug 15, 2004 3:35 pm
by Dreamsmith
Try this:

Code: Select all

#define fork() ({pid_t p; asm("syscall":"a"(SYS_FORK): "a"(p)); p;})
Note three things: the curly braces, the final semicolon, and the fact that any register mentioned in the input or output registers should never appear in the clobbers -- either it has the values you specfied or its clobbered unpredictably, it can't possibly be both at once...

Re:single function with multiple names

Posted: Mon Aug 16, 2004 12:58 am
by Solar
Candy wrote: think I'm going to use...
That's exactly what I'd have done (since I loathe #define's).

Re:single function with multiple names

Posted: Mon Aug 16, 2004 1:09 am
by Candy
Dreamsmith wrote:

Code: Select all

#define fork() ({pid_t p; asm("syscall":"a"(SYS_FORK): "a"(p)); p;})
Note three things: the curly braces, the final semicolon, and the fact that any register mentioned in the input or output registers should never appear in the clobbers -- either it has the values you specfied or its clobbered unpredictably, it can't possibly be both at once...
Ok... now, the final question, how do I make it push a bunch of registers as if it was going to do a normal call xxx, and then replace that call xxx with (mov al, SYSCALL_NUM; syscall) ? Making it a define nullifies the pushing idea, inline functions the same, but it won't just make a syscall out of it.

Re:single function with multiple names

Posted: Mon Aug 16, 2004 2:03 pm
by Dreamsmith
Candy wrote:Ok... now, the final question, how do I make it push a bunch of registers as if it was going to do a normal call xxx, and then replace that call xxx with (mov al, SYSCALL_NUM; syscall) ?
Just code it that way, perhaps? Preface the mov/syscall with a few push instructions. E.g.:

Code: Select all

#define kill(int pid) ({int result; \
  asm("push %1\n\t" \
       "move al,$SYSCALL_KILL\n\t" \
       "syscall" : "=a"(result) : "g"(pid)); \
  result;})
Might need to add a stack adjust after the syscall, depending on your calling conventions.

Re:single function with multiple names

Posted: Tue Aug 17, 2004 1:38 am
by Pype.Clicker
Candy wrote: OK, thanks, didn't know that. I was afraid it'd wreck the code structure etc., don't completely trust #define's myself. Inlines aren't inlined on -O0 so that wasn't the best option either.
Honestly, i don't worry too much about that "-O0" and always compile with "-O3" ...

Re:single function with multiple names

Posted: Tue Aug 17, 2004 5:52 am
by Candy
Dreamsmith wrote: Just code it that way, perhaps? Preface the mov/syscall with a few push instructions. E.g.:

...

Might need to add a stack adjust after the syscall, depending on your calling conventions.
And this doesn't work (nicely?) for variable arguments, where I'd just want it to push all as if it was a normal function, only to replace the call xxxx with the mov al, x;syscall;nop.

Re:single function with multiple names

Posted: Tue Aug 17, 2004 6:32 am
by Pype.Clicker
except by using a trampoline (that is, an actual *call* followed by a *syscall* in the called function), i don't see much solutions ...

That was roughly what call gates were trying to solve (except that 32 bits compilers don't support far calls anyway)

Re:single function with multiple names

Posted: Tue Aug 17, 2004 6:59 am
by Candy
Pype.Clicker wrote: except by using a trampoline (that is, an actual *call* followed by a *syscall* in the called function), i don't see much solutions ...

That was roughly what call gates were trying to solve (except that 32 bits compilers don't support far calls anyway)
I was considering making the ugliest hack I've ever... making either a recursive define or about 60 or so defines so all functions can be used with it... That'd work...