jobrien@nixbur.UUCP (John O'Brien) (10/31/90)
Is there some way to change a symbol's class to "static" in a ".o" file? Suppose I have a ".c" file with functions "a" and "b", and global variables "x" and "y": int c, d; a() { ... } b() { ... } Suppose also that I have another ".c" file that refers to "a", "b", "c" and "d": external int c, d; spot() { ... a(); b(); ... } so I can't just make any of the symbols "static". Now suppose that I want to use the function "spot" two ways: I want to link it in with my own application, where I am not worried about "a" and "b" being linked in inadvertently, and I also want to make "spot" and only "spot" available to someone else for linking. I think it would be possible to combine the two ".o" files into one ".o" file, but would it then be possible to change the class of "a", "b", "c" and "d" to static so that they would not be exported to the linker? Thanks internet: obrien.bur@nixdorf.com uucp: linus!nixbur!jobrien Flying saucers, levitation/Yo! I can do that! - D. Byrne
gwyn@smoke.brl.mil (Doug Gwyn) (11/01/90)
In article <781@nixbur.UUCP> jobrien@nixbur.UUCP (John O'Brien) writes: >Is there some way to change a symbol's class to "static" in a ".o" file? Technically, there probably is, but it wouldn't solve whatever problem you think it would. >but would it then be possible to change the class of "a", "b", "c" >and "d" to static so that they would not be exported to the linker? You're missing an important point: spot() REQUIRES that definitions be provided for a() and b(). Changing these to private rather than global symbols wouldn't magically define suitable functions! In some (non standard conforming) implementations, c and d might already be compiled into references to "common" storage, so they would get storage defined for them even if there were no explicit definition in the set of modules being linked. My recommendation is to design the kind of external interfaces you really want, rather than trying to override the design via the linker.
jobrien@nixbur.UUCP (John O'Brien) (11/01/90)
In article <14294@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >You're missing an important point: spot() REQUIRES that definitions >be provided for a() and b(). Changing these to private rather than >global symbols wouldn't magically define suitable functions! In some >(non standard conforming) implementations, c and d might already be >compiled into references to "common" storage, so they would get >storage defined for them even if there were no explicit definition in >the set of modules being linked. Let me try again. I'm already referring the symbols a,b,c and d from several places (they are utility functions), so I can't just make them static. What I want to do takes two steps. Assume the file with a, b, c, and d is named "one.c", and the file with spot is named "two.c" and both files have been compiled to ".o" files. The first step is to link "one" and "two" into another ".o" file: ld -r -o big.o one.o two.o This creates a ".o" file by combining "one.o" and "two.o" into "big.o", which contains all of the definitions and which has external symbols a, b, c, d, and spot. Now, if it is possible to change a, b, c, and d to "static" class, when another program links in big.o a, b, c, d are not exported but can be referred to within "big.o". Nobody ever links in more than one pass, so this approach is not commonly understood (by me, either). > >My recommendation is to design the kind of external interfaces you >really want, rather than trying to override the design via the linker. This code is here, this code has been extensively tested, this code is called from many different places. Part of the design requirements is that I link in this code and not copy the source (this is to avoid hav- ing to maintain two pieces of code that do the same thing). John
gwyn@smoke.brl.mil (Doug Gwyn) (11/02/90)
In article <783@nixbur.UUCP> jobrien@nixbur.UUCP (John O'Brien) writes: > ld -r -o big.o one.o two.o >Part of the design requirements is that I link in this code and not copy >the source (this is to avoid having to maintain two pieces of code that >do the same thing). Thanks for the additional information. I don't think in most environments this approach can be made to work, because while you're still outputting a .o file the final link-image relocation has not yet been done, and if your compiler generates external linkages in certain commonly-encountered ways, you simply can't get "ld" to provide "position-independent code" for the linkages between one.o and two.o; it will be necessary to retain the relocation information. I think that some, maybe all, versions of "ld" would fail to complete the relocation if you were to somehow change the intermodule references to have the STATIC attribute. Here is one possibility that doesn't require playing tricks with the linker: /* file one.c: */ #ifndef STATIC #define STATIC /* nothing */ #endif STATIC int c, d; STATIC a() { ... } STATIC b() { ... } /* file two.c: */ #ifdef STATIC #include "one.c" #else external a(), b(); external int c, d; #endif spot() { ... a(); b(); ... } Thus, if you type cc -c one.c cc -c two.c you get the same object code that you started with, but if you type cc -c -DSTATIC=static two.c you get one object "two.o" that contains only one external name, "spot". Of course, you can make this approach more aesthetically appealing by using an auxiliary header file that defines the interface to the "one.c" facilities; you should in general do that anyway as a matter of good program design. So, for example, /* file one.c: */ /* file one.h: */ #include "one.h" #ifndef STATIC STATIC int c, d; #define STATIC /* nothing */ STATIC a() extern int c, d; { extern a(), b(); ... #else /* STATIC = "static" */ } #ifndef BEEN_HERE STATIC b() #define BEEN_HERE { #include "one.c" ... #endif } #endif /* file two.c: */ #include "one.h" spot() { ... a(); b(); } We've used similar methods here to control whether or not some subset of potentially external symbols get "hidden" when modules are added to a library; some of our debuggers are more helpful when the symbols are not hidden, i.e., not file-static, so we like to leave them visible until we've finished debugging the modules. This nice thing is that this method is portable. (If you use a configuration header, say, "config.h" or "std.h", to optionally predefine STATIC and to set up flags for other environmental dependencies, then it becomes fully portable, and you don't have to specify "-DSTATIC=static" to the compiler.)
richard@aiai.ed.ac.uk (Richard Tobin) (11/02/90)
In article <781@nixbur.UUCP> jobrien@nixbur.UUCP (John O'Brien) writes: >Is there some way to change a symbol's class to "static" in a ".o" file? Almost certainly. Examine the format of symbol table entries, and see what you can do. There will be include files describing it - a.out.h perhaps, and a man page for a.out. Then write a program which reads in the .o file, and writes it out with a modified symbol table. A simple hack which may be enough is just to edit the .o file (using an editor like gnu emacs which doesn't have line length restrictions). Find the symbol name and change it to something obscure, being careful not to change its length. -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
srodawa@vela.acs.oakland.edu (Ron Srodawa) (11/03/90)
In article <3693@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes: >In article <781@nixbur.UUCP> jobrien@nixbur.UUCP (John O'Brien) writes: >>Is there some way to change a symbol's class to "static" in a ".o" file? > >Almost certainly. Examine the format of symbol table entries, and see what Uh? Static variables are allocated storage in a different place than non-static variables. Non-static local variables are allocated on the stack, static variables along with the text. I would expect the easiest fix is a recompile. If youy REALLY wanted to try it, you would have to increase the length of the module, note where the new space is, then change EVERY reference to the variable to the new location. This will change the address mode you will use and the new instruction may be shorter or longer than the instruction it replaces. I wouldn't even attempt to try this. Ron. -- | Ronald J. Srodawa | Internet: srodawa@unix.secs.oakland.edu | | School of Engineering and CS | UUCP: srodawa@egrunix.UUCP | | Oakland University | Voice: (313) 370-2247 | | Rochester, Michigan 48309-4401 | |
gwyn@smoke.brl.mil (Doug Gwyn) (11/03/90)
In article <3653@vela.acs.oakland.edu> srodawa@vela.acs.oakland.edu (Ron Srodawa) writes: >Non-static local variables are allocated on the stack, ... The original question concerned global, i.e., file-scope, identifiers, not auto variables. Use of the word "STATIC" is unfortunate, since in C the "static" keyword is semantically overloaded.
cgy@cs.brown.edu (Curtis Yarvin) (11/05/90)
In article <3653@vela.acs.oakland.edu> srodawa@vela.acs.oakland.edu (Ron Srodawa) writes: >In article <3693@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes: >>In article <781@nixbur.UUCP> jobrien@nixbur.UUCP (John O'Brien) writes: >>>Is there some way to change a symbol's class to "static" in a ".o" file? >> >>Almost certainly. Examine the format of symbol table entries, and see what > >Uh? Static variables are allocated storage in a different place than >non-static variables. Non-static local variables are allocated on the >stack, static variables along with the text. I would expect the easiest It would appear we have a terrible misunderstanding here; so, before we get an accidental flame war, let's break this thing up. There are two things you can do with the "static" keyword in C. You can tell the compiler to keep a _local_ variable in the data segment instead of the stack. Or you can prevent routines in other files from accessing a _global_ variable in a file. The first cannot be altered without a good disassembler. The second can. Which the original poster was referring to is anyone's guess; maybe he can post again & tell us. -Curtis "I tried living in the real world Instead of a shell But I was bored before I even began." - The Smiths
jobrien@nixbur.UUCP (John O'Brien) (11/06/90)
>Uh? Static variables are allocated storage in a different place than >non-static variables. Non-static local variables are allocated on the >stack, static variables along with the text. I would expect the easiest >fix is a recompile. If youy REALLY wanted to try it, you would have to >increase the length of the module, note where the new space is, then >change EVERY reference to the variable to the new location. This will >change the address mode you will use and the new instruction may be shorter >or longer than the instruction it replaces. I wouldn't even attempt to >try this. Ron. Actually I was much more concerned about the functions (which are always in the "text" section) than the variables. My question was, if I did what I was proposing to do, would symbols that been changed to static in big.o still be visible throughout "big.o", and would they be exported to the linker? I don't know COFF very well, but it seems to me that in the example I gave it seems to me that the variables "c" and "d" would be in the "bss" (uninitialized data) section whether or not they were static because they exist through out the program, and do not have initial values. I just simply want some control of which symbols are exported to the linker. John