Path: utzoo!attcan!uunet!nih-csl!lhc!adm!cmcl2!yale!cs.utexas.edu!usc!apple!agate!ucbvax!CompuServe.COM!72347.2767 From: 72347.2767@CompuServe.COM (Robert Delius Royar) Newsgroups: comp.sys.atari.st.tech Subject: Re: How to set variables Message-ID: <"901115133200.72347.2767.EHA29-1"@CompuServe.COM> Date: 15 Nov 90 13:32:01 GMT Sender: daemon@ucbvax.BERKELEY.EDU Lines: 87 Re: your question posted to comp.sys.atari.st.tech for info on how to modify variables in an executable file, there are a number of ways. I assume you need to modify the variables in a disk file--i.e. you are not looking to change them in a running program, to un-fixup the program, and then to write them back to disk. That could get real hary. I can think of two easy ways to accomplish this. One requires some assembly. The other requires you to leave symbols in the executable. I'll describe the former. The latter is the method used by GNU C top do just what you are looking for. Finding the executable on disk The first step is to find the executable on disk. This may be easy or difficult depending on the TOS level and on the type of program you are running. TOS does not store the name of the currently executing process in an accessible place, but the AES does store this if you Pexec from an AES program and use the following in your init routine, before adjusting paths and such: char myname[128], command[128]; appl_init(); shel_read(myname,command); Unfortunately before Rainbow TOS, the rscrc_load() function and others trash the shel_read() buffers. TOS 1.4 onward doesn't exhibit this problem. On return from shel_read() myname will contain the name (and possibly the path) of the executing process. Command will contain the command from the invocation of myname. A simpler way to find the name is to require that it remain constant and to require the program be invoked from its own directory. Then you don't have to find it--it's always where you expect. Modifying variables The TOS executable format requires each program (even overlays) to begin with a 28-byte header. This header "disappears" once the program is loaded for execution. More accurately, parts of it are stored in the executable's basepage. The so-called magic number (0x60 0x1a) that must be at the start of every executable file is actually a bra.b 0x1a instruction, which on earlier Alcyon 68K systems caused execution to begin at 28 bytes passed the beginning. TOS does not interpret the magic the same way, but execution begins with the first address of the .text which is 28 bytes past beginning of the header. The effect is the same. You can store variables right after the beginning of the .text as long as you jump around those variables. With a little figuring, you can safely modify those variables on disk and save the results. Here are some code fragments: * This fragment sets up the variable table * Must be first object file in link statement * .globl __start * this is the runtime entry routine in gemstart.s .globl _vartab .globl _var1 .globl _var2 .globl _var3 jmp __start _vartab: _var1: dc.l 0 _var2: dc.l 0 _var3: dc.l 0 /* this C fragment opens the file, finds the current variable values, and * changes them */ char buf[3*sizeof(long)]; char myname[128], command[128]; appl_init(); shel_read(myname,command); if ((fd=Fopen(myname,2)) < 0) { Cconws("Cannot open "); Cconws(myname); Cconws("\r\n"); Pterm(fd); } else Fseek(0x22L,fd,0); /* now points to vartab */ Fread(fd,(long)(3*sizeof(long)),buf); modify_buf(buf); /* make your changes */ Fseek(0x22L,fd,0); /* 0x1c + sizeof(jmp __start) == 0x22L */ Fwrite(fd,(long)(3*sizeof(long)),buf); /* write them back */ Fclose(fd); I've used the above in a number of programs without problems. Hope yo find this useful. Robert Royar Cratylus Educational Software