From: James Gessling [jgessling@yahoo.com] Sent: Monday, July 01, 2002 2:44 PM To: Info-VAX@Mvb.Saic.Com Subject: Linking shareable with SYMBOL_VECTOR (long) Greetings, I had asked some questions regarding shareable image vectors and how to ensure they stay stable when adding or removing functions. I got some good advice, and decided to understand this once and for all. The key to it all is that in the vector the entry points are simply a list of offsets. You can always add to the end because that doesn't change any of the existing offsets, but mess about in the middle at your peril. I did some experiments and present them here. Kind of long but I thought entertaining. This is what I did. First made a shareable image with three entry points. The option file looks like (all.opt) this: case_sensitive=YES SYMBOL_VECTOR=( - func1=PROCEDURE, - func2=PROCEDURE, - func3=PROCEDURE - ) Each function was like this (func2.c): #include stdio void func2() { printf("Hi, I'm func2\n"); } Built the shareable image like this: $ cc/names=as_is func1,func2,func3 $ link/share=func.exe func1,func2,func3,all.opt/opt Now made a test function that looked like this (test.c): void func2(); void main() { func2(); } And built it like this: $ define func sys$disk:[]func.exe $ cc/names=as_is test $ link test,sys$input/opt func/share When run, it does this: $ run test Hi, I'm func2 Now for some fun, First I simply relinked func.exe, same files, no change to commands. But look at this: $ run test %DCL-W-ACTIMAGE, error activating image FUNC -CLI-E-IMGNAME, image file $7$DKA105:[DEVUSER3.][]FUNC.EXE;10 -SYSTEM-F-SHRIDMISMAT, ident mismatch with shareable image That was educational! Seems linker will generate a major and minor ident based on bits from the time and set the match control to ISD$K_MATEQU meaning test.exe needs to have exactly the same major/minor ident as func.exe but in this case it doesn't hence the error. Looks like I need to take control of gsmatch. I added this line to all.opt and relinked func.exe and test.exe GSMATCH=LEQUAL,1,0 Please note that test.exe is never touched from here on, only the shareable func.exe is rebuilt in different ways. Now to simulate my (real) problem. I had inadvertently removed a function without leaving a placeholder. So all.opt looked something like: GSMATCH=LEQUAL,1,0 case_sensitive=YES GSMATCH=LEQUAL,1,0 SYMBOL_VECTOR=( - func1=PROCEDURE, - func3=PROCEDURE - ) I rebuild func.exe $ run test Hi, I'm func3 This makes sense, test.exe was linked when it's call was mapped to the second function in the table. Now when it's run the second entry is func3, so it goes ahead and calls it. This is obviously a very bad situation, you can't have your system making calls you don't expect. When making such an incompatible change in the vector, I should have bumped the major ident, say to 2. Then when test.exe is run it will get the SHRIDMISMAT error. How about if the vector is shortened to the point where your desired entry point is "off the end". In this case VMS saves you. I rebuilt func.exe with this all.opt. case_sensitive=YES GSMATCH=LEQUAL,1,0 SYMBOL_VECTOR=( - func1=PROCEDURE - ) Now $ run test %IMGACT-F-SYMVECMIS, shareable image's symbol vector table mismatch -IMGACT-F-FIXUPERR, error when TEST referenced FUNC So, how can we obsolete a function and keep the other calls working. There are three options, using the SPARE keyword, using PRIVATE, or providing a placeholder function. Back to the original all.opt (three entry points) I replaced func2 with SPARE, like this: case_sensitive=YES GSMATCH=LEQUAL,1,0 SYMBOL_VECTOR=( - func1=PROCEDURE, - SPARE, - func3=PROCEDURE - ) Now, try our test programs (calls func2) $ run test %SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=000000000000 0000, PC=0000000000000000, PS=0000001B %TRACE-F-TRACEBACK, symbolic stack dump follows image module routine line rel PC abs PC 0 0000000000000000 0000000000000000 TEST TEST main 4 00000000000000C8 00000000000200C8 TEST TEST __main 0 0000000000000070 0000000000020070 0 FFFFFFFF90EAD3F4 FFFFFFFF90EAD3F4 Maybe not the best way to let the program know that func2 doesn't exist anymore. How about letting existing programs that use func2 keep working but not allow new programs to call it. This uses the PRIVATE keyword in the options file. Like this: case_sensitive=YES GSMATCH=LEQUAL,1,0 SYMBOL_VECTOR=( - func1=PROCEDURE, - func2=PRIVATE, - func3=PROCEDURE - ) Rebuilding func.exe with this and now run test. It does: $ run test Hi, I'm func2 Try to link a new test.exe that calls func2 against the shareable results in: $ link test,sys$input/opt func/share %LINK-W-NUDFSYMS, 1 undefined symbol: %LINK-I-UDFSYM, func2 %LINK-W-USEUNDEF, undefined symbol func2 referenced in psect $LINK$ offset %X00000020 in module TEST file DEV$USER:[xxx]TEST.OBJ;1 Probably will result in an irritated phone call that the link which worked fine yesterday doesn't now and fix it right away. But at least the message gets out to stop using the obsolete routine without breaking current working stuff. How about making a placeholder routine that generates a useful error message. Like this error.c: #include stdio void error() { printf("Sorry, this function not supported anymore\n"); } Then change all.opt to be like: case_sensitive=YES GSMATCH=LEQUAL,1,0 SYMBOL_VECTOR=( - func1=PROCEDURE, - error=PROCEDURE, - func3=PROCEDURE - ) Rebuilding func.exe like: $ link/share=func.exe func1,error,func3,all.opt/opt Now $ run test Sorry, this function not supported anymore Obviously, this error could be better, and probably should cease execution of the image since it needed something that wasn't there anymore. Well, that about covers it for now. Hope I've helped someone out. Jim