Title: | ** Hackers ** |
Moderator: | XDELTA::HOFFMAN |
Created: | Mon Feb 01 1988 |
Last Modified: | Tue May 27 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 1838 |
Total number of notes: | 13578 |
have any of you ever used ldr$unload_image? do you know anyone or any project that might have tried it? do any of you have any hints or warnings about replacing an execlet on the fly? thanks.
T.R | Title | User | Personal Name | Date | Lines |
---|---|---|---|---|---|
1832.1 | ZIMBRA::BERNARDO | Dave Bernardo, VMS Engineering | Wed Mar 26 1997 00:09 | 6 | |
ldr$unload_image can only unload an execlet which was previously loaded so that it _could_ be unloaded.... so, how are you planning to use it? d. | |||||
1832.2 | EEMELI::MOSER | Orienteers do it in the bush... | Wed Mar 26 1997 09:24 | 9 | |
I persoanlly have done this when writing an execlet and testing it, so I didn't have to reboot every time, but there are gotchas you need to know, otherwise you trigger an automatic reboot (== bugcheck). I do not recommend that for a production environment, and as Dave said you need to load it correctly so you can use the unload. I'll post my load/unload hack in the next reply (saince this is hackers...) /cmos | |||||
1832.3 | EEMELI::MOSER | Orienteers do it in the bush... | Wed Mar 26 1997 09:26 | 235 | |
1832.4 | considering trying it | CPEEDY::BRADLEY | Chuck Bradley | Wed Mar 26 1997 14:15 | 26 |
re .1, what am i trying to do? similar to .2, we could save a lot of time testing if we could unload an execlet. in pathworks, we have an execlet to implement streams and we use it for various communications protocols. we build several times per week and each new installation requires a reboot. it would be nice to avoid the reboot. some customers report problems, and sometimes we have to collect more information to solve the problem. sometimes it takes an instrumented version of the software to gather the information. the customer does not want to reboot just to gather information, so he waits until the next scheduled or accidental downtime to install the instrumented software. as a result it takes a longer time to solve the problem. CLD turnaround time is a major concern this year. someone worked on this for a while, but did not have a full solution when they left the company. i wanted to be sure it was possible before looking further. ldr$unload_image does not seem to be documented for the outside world, so it was easy to imagine that it was only half implemented. the existence proof in .3 is reassuring. re .3, sample of use: thank you. after i study it, and review what has been done here, i may have some more questions. | |||||
1832.5 | Suggestions, Pointers... | XDELTA::HOFFMAN | Steve, OpenVMS Engineering | Wed Mar 26 1997 15:06 | 13 |
There are some ldr$* and *image* keywords here... Have you considered an execlet that contains vector(s) to the real execlet(s)? This would let you "update" the code on the fly. (You might not be able to unload the code, but generating pool large enough to support some no-longer-needed code might be easier than the reboot appears to be.) My preference is usually to use a pseudo device driver as a "shell" for loadable code, as one can easily add more of these, and one has a nice user-mode-accessable "control interface" available. | |||||
1832.6 | thanks. lots of pool used | CPEEDY::BRADLEY | Chuck Bradley | Wed Mar 26 1997 16:56 | 24 |
re .5: thanks for the suggested keywords. i'll check them out. so few conferences have useful and up to date keywords, that i didn't even try. i made about a half dozen tries with dir/title=foo and found very little -- unloading a device driver, repeated initialization. so i scanned the entire directory looking for related titles. when i didn't see anything useful, i entered .0. we might be able to afford losing the space occupied by the image to be replaced, but i think there is many times that much in data buffers. this is just a hunch, not an estimate or even an educated guess, but i suspect doing it as bad as i can get away with is at least 3/4 of the effort to do it right. i'll also look at the pseudo device driver. i've only looked at a tiny fraction of the code, but that part is well organized. all of the allocated pool is on multiple lists and it looks like i can give it all back exactly once. thanks, again for the suggestions and the pointers. BTW, silence here does not necessarily mean success. this might not even make it to the top of the list of things to work on. | |||||
1832.7 | ZIMBRA::BERNARDO | Dave Bernardo, VMS Engineering | Wed Mar 26 1997 21:25 | 17 | |
If you decide to go the unload route, you'll need to initially load your execlets with the LDR$V_UNL bit set. And, you will also have to make sure that nothing is using the execlet while you are trying to unload it... or you'll get to see the reboot feature of the ldr routines in action. One of the features execlets were intended to have were unload routines. Similar to initialization routines but at the other end of the rainbow. So, you _could_ try to use this feature to deallocate your memory. But, you will probably be the first. I own the exec loader on Alpha VMS and I know that everything else works. But, no one uses the unload routine stuff, so I can't say if it does. And lastly, the ldr$ routines got documented in V7.1... in the Programming Concepts book. d. | |||||
1832.8 | It can be done.... | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:39 | 21 |
Well, you can load as well as unload. Some time ago i created some stuff to load and unload a module on the fly. The main routine to do the processing is called from macro and written in C, it was some process state monitor. The problem i ran into was that real dynamic unloading support is not compiled in the VMS kernel. I don't have the right details in my head, but you should be able to specify an unload routine in a seprarate psect, and by specifying a flag it should be called. But this code is currently not included in the kernel. The next replies contain example code. .+1 = BUILD.COM, the build procedure .+2 = ARCH.MAR, used for conditional compilation for Vax or Alpha .+3 = SMON.MAR, the main routine .+4 = SMONLOAD.C, the dynamic loader .+5 = SMONUNLOAD.C, the dynamic unloader .+6 = PROCPROC.C, the C routine called by the main routine to do some processing. Jur. | |||||
1832.9 | BUILD.COM | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:39 | 93 |
$ if f$getsyi("hw_model") .gt. 1023 $ then $ alpha = 1 $ else $ alpha = 0 $ endif $ if alpha $ then $ if p1 .nes. "" then goto linka $ macro/obj=smon arch+smon+sys$library:lib/lib $ cc/define="ALPHA"/instruct=nofloat/extern=strict- /warning=disable=globalext procproc+sys$library:sys$lib_c/lib $ cc/define="ALPHA" smonload+sys$library:sys$lib_c/lib $ cc/define="ALPHA" smonunload+sys$library:sys$lib_c/lib $linka: $ link/notrace/sysexe smonload $ link/notrace/sysexe smonunload $ link/native_only/bpages=14/section/replace/notraceback/nosysshr/vms_exec- /nodemand_zero/contiguous/share=smon.exe/map=smon/cross/full sys$input:/opt cluster=smon,,,smon,procproc,sys$library:starlet/include=(sys$doinit) sys$loadable_images:sys$base_image.exe/share/sele psect_attr = $linkage , PIC,GBL,NOSHR,NOEXE, RD, WRT psect_attr = exec$init_linkage , PIC,USR,CON,REL,GBL,NOSHR,EXE,RD,WRT,NOVEC psect_attr = exec$init_code , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_000 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_001 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_002 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_sstbl_000 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_sstbl_001 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = exec$init_sstbl_002 , PIC,GBL,NOSHR, EXE, RD, WRT psect_attr = $link$ , PIC,WRT psect_attr = $initial$ , PIC,WRT psect_attr = $literal$ , PIC,NOSHR,WRT psect_attr = $readonly$ , PIC,NOSHR,WRT psect_attr = $code$ , PIC,GBL,NOSHR, EXE, RD, NOWRT psect_attr = $data$ , PIC,GBL,NOSHR, NOEXE, RD, WRT psect_attr = $bss$ , PIC,GBL,NOSHR, NOEXE, RD, WRT collect = nonpaged_readonly_psects/attributes=resident,- exec$nonpaged_code,$code$ collect = nonpaged_readwrite_psects/attributes=resident,- exec$nonpaged_data,$data$,$link$,$literal$,$bss$,- $readonly$,$linkage,exec$nonpaged_linkage collect = initialization_psects/attributes=initialization_code - , exec$init_code - , exec$init_000 - , exec$init_001 - , exec$init_002 - , exec$init_linkage - , exec$init_sstbl_000 - , exec$init_sstbl_001 - , exec$init_sstbl_002 $ else $ if p1 .nes. "" then goto linkv $ macro smon+sys$library:lib/lib $ cc procproc $ cc smonload $ cc smonunload $linkv: $ link/notrace smonload,sys$input/opt sys$share:vaxcrtl.exe/share sys$system:sys.stb/selective $ link/notrace smonunload,sys$input/opt sys$share:vaxcrtl.exe/share sys$system:sys.stb/selective $ link/nosysshr/notraceback/share=smon/contiguous- /symbol=smon/map=smon/full/cross sys$input/opt sys$library:starlet/include:(sys$doinit),- sys$disk:[]smon,procproc,- sys$system:sys.stb/selective vector_table=sys$system:sys.stb psect_attr=$code,noshr psect_attr=$char_string_constants,noshr collect=nonpaged_readonly_psects/attributes=resident,- exec$nonpaged_code,$code collect=nonpaged_readwrite_psects/attributes=resident,- exec$nonpaged_data,$data,$char_string_constants collect=paged_readonly_psects,- exec$paged_code collect=paged_readwrite_psects,- exec$paged_data collect=initialization_psects/attributes=initialization_code,- exec$init_code,- exec$init_000,- exec$init_001,- exec$init_002,- exec$init_pfntbl_001,- exec$init_pfntbl_002,- exec$init_pfntbl_003,- exec$init_sstbl_000,- exec$init_sstbl_001,- exec$init_sstbl_002 $ endif $ copy/log smon.exe sys$common:[sys$ldr] | |||||
1832.10 | ARCH.MAR | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:40 | 1 |
alpha==1 | |||||
1832.11 | SMON.MAR | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:40 | 116 |
.title Smon - Process state monitor .ident /V1.0/ .library 'sys$library:lib' $ipldef $tqedef $ldrimgdef $inirtndef .if df alpha $ldrdef .endc .macro return .if df alpha ret .iff rsb .endc .endm DECLARE_PSECT EXEC$INIT_CODE .if df alpha INITIALIZATION_ROUTINE NAME=SMON$INIT .iff INITIALIZATION_ROUTINE NAME=SMON$INIT,- SYSTEM_RTN=1 .endc ; ; Input: R4 = LDRIMG block ; R5 = Address of flags longword ; R0,R1,R2,R3 = scratch ; smon$init: .if df alpha .call_entry input=<r4,r5>,- output=<r0> .endc movzwl #ss$_normal,r0 bbs #inirtn$v_called,(r5),20$ setipl #ipl$_astdel,- environ=uniprocessor ; Avoid scheduling ; ; Now allocate the TQE and queue it to the system. ; pushr #^m<r2,r3,r4,r5> jsb g^exe$alloctqe ; Allocate a timer entry blbc r0,10$ ; Any errors ? movl r2,tqeadr ; ; Now setup the TQE to contain the correct parameters. ; movab action,tqe$l_fpc(r2) ; Setup the rtn address movb #tqe$c_ssrept,tqe$b_rqtype(r2) ; Make it repeatable movl r2,r5 ; Copy the TQE address movq g^exe$gq_systime,r0 ; Get current time .iif df alpha, .disable flagging movq #^D1000000,tqe$q_delta(r5) ; 10 Ms delta time .iif df alpha, .enable flagging jsb g^exe$instimq ; Insert it in the queue movab smon$unload,unlvec ; Setup address of unload routine .if ndf alpha bisl2 #inirtn$m_sysrtn,unlvec+4 .endc moval unlvec,ldrimg$l_unlvec(r4) ; Setup address of unload vector movzwl #ss$_normal,r0 10$: setipl #0,- environ=uniprocessor ; Restore IPL popr #^m<r2,r3,r4,r5> 20$: blbc r0,30$ ; Stop in case of error calls #0,procinit ; Init of main code 30$: return ; Return to the caller DECLARE_PSECT EXEC$NONPAGED_CODE action: .if df alpha .call_entry .endc lock sched calls #0,procproc unlock sched return ; smon$unload: .if df alpha .call_entry output=<r0> .endc movl tqeadr,r4 jsb g^exe$rmvtimq blbc r0,10$ movl r4,r0 jsb g^exe$deanonpaged movzwl #ss$_normal,r0 10$: return DECLARE_PSECT EXEC$NONPAGED_DATA tqeadr: .long 0 ; Our TQE address unlvec: .long 0 ; Unload routine address .long 0 ; Flags .long 0 ; Termination of chain ; DECLARE_PSECT EXEC$UNL_001 ; ; .address smon$unload ; .long 0 .end | |||||
1832.12 | SMONLOAD.C | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:40 | 73 |
#include <stdio.h> #include <descrip.h> #include <psldef.h> #include <lnmdef.h> #include <starlet.h> #include <lib$routines.h> #define IMAGE "SMON.EXE" #define TABLE "LNM$SYSTEM_TABLE" #define LOGNAM "SMON$HANDLE" #ifdef ALPHA #include <ldrdef.h> #else #ifndef LDR_DYN$M_UNL #define LDR_DYN$M_UNL 2 #endif #endif typedef struct itmlst { short size; short item; char *buffer; char *retlen; } ITEMS; int ldr$load_image(); int main() { int stat; unsigned int handle[3]; unsigned int arglist[4]; $DESCRIPTOR(imgdsc,IMAGE); $DESCRIPTOR(tblname,TABLE); $DESCRIPTOR(logname,LOGNAM); ITEMS lnmlst[4]; char h1[9], h2[9], h3[9]; arglist[0] = 3; arglist[1] = (int) &imgdsc; #ifdef ALPHA arglist[2] = LDR$M_UNL; #else arglist[2] = LDR_DYN$M_UNL; #endif arglist[3] = (int) handle; stat = sys$cmkrnl(&ldr$load_image,arglist); if (!(stat & 1)) lib$stop(stat); printf("Image %s loaded successfully.\nAddress:\t%08.8X\nLDRIMG block:\t%08.8X\nSeq. number:\t%08.8X\n", IMAGE, handle[0], handle[1], handle[2]); sprintf(h1,"%08.8X",handle[0]); sprintf(h2,"%08.8X",handle[1]); sprintf(h3,"%08.8X",handle[2]); lnmlst[0].size = 8; lnmlst[0].item = LNM$_STRING; lnmlst[0].buffer = h1; lnmlst[0].retlen = 0; lnmlst[1].size = 8; lnmlst[1].item = LNM$_STRING; lnmlst[1].buffer = h2; lnmlst[1].retlen = 0; lnmlst[2].size = 8; lnmlst[2].item = LNM$_STRING; lnmlst[2].buffer = h3; lnmlst[2].retlen = 0; lnmlst[3].size = 0; lnmlst[3].item = 0; stat = sys$crelnm(0,&tblname,&logname,&PSL$C_EXEC,&lnmlst); if (!(stat & 1)) lib$stop(stat); } | |||||
1832.13 | SMONUNLOAD.C | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:40 | 81 |
#include <stdio.h> #include <descrip.h> #include <psldef.h> #include <lnmdef.h> #include <starlet.h> #include <lib$routines.h> #define IMAGE "SMON.EXE" #define TABLE "LNM$SYSTEM_TABLE" #define LOGNAM "SMON$HANDLE" typedef struct itmlst { short size; short item; char *buffer; short *retlen; } ITEMS; int ldr$unload_image(); int main() { int stat; unsigned int handle[3]; unsigned int arglist[3]; $DESCRIPTOR(imgdsc,IMAGE); $DESCRIPTOR(tblname,TABLE); $DESCRIPTOR(logname,LOGNAM); ITEMS lnmlst[7]; char h1[9], h2[9], h3[9]; short l1, l2, l3; int idx1, idx2, idx3; idx1 = 0; idx2 = 1; idx3 = 2; lnmlst[0].size = 4; lnmlst[0].item = LNM$_INDEX; lnmlst[0].buffer = (char *) &idx1; lnmlst[0].retlen = 0; lnmlst[1].size = 8; lnmlst[1].item = LNM$_STRING; lnmlst[1].buffer = h1; lnmlst[1].retlen = &l1; lnmlst[2].size = 4; lnmlst[2].item = LNM$_INDEX; lnmlst[2].buffer = (char *) &idx2; lnmlst[2].retlen = 0; lnmlst[3].size = 8; lnmlst[3].item = LNM$_STRING; lnmlst[3].buffer = h2; lnmlst[3].retlen = &l2; lnmlst[4].size = 4; lnmlst[4].item = LNM$_INDEX; lnmlst[4].buffer = (char *) &idx3; lnmlst[4].retlen = 0; lnmlst[5].size = 8; lnmlst[5].item = LNM$_STRING; lnmlst[5].buffer = h3; lnmlst[5].retlen = &l3; lnmlst[6].size = 0; lnmlst[6].item = 0; stat = sys$trnlnm(0,&tblname,&logname,&PSL$C_EXEC,&lnmlst); if (!(stat & 1)) lib$stop(stat); h1[l1] = '\0'; h2[l2] = '\0'; h3[l3] = '\0'; sscanf(h1,"%x",&handle[0]); sscanf(h2,"%x",&handle[1]); sscanf(h3,"%x",&handle[2]); arglist[0] = 2; arglist[1] = (int) &imgdsc; arglist[2] = (int) handle; stat = sys$cmkrnl(&ldr$unload_image,arglist); if (!(stat & 1)) lib$stop(stat); stat = sys$dellnm(&tblname,&logname,&PSL$C_EXEC); if (!(stat & 1)) lib$stop(stat); } | |||||
1832.14 | PROCPROC.C | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:40 | 137 |
#ifdef ALPHA #include <pcbdef.h> #else typedef struct _pcb { char dummy1[26]; unsigned short pcb$w_state; char dummy2[284]; unsigned char pcb$t_lname[16]; } PCB; #endif #include <starlet.h> #include <ssdef.h> int p_strlen(); int p_strncmp(); char *p_strcpy(); void p_bzero(); globalref unsigned long int sch$gl_pcbvec; globalref unsigned long int sch$gl_maxpix; struct proctbl { char proclen; char procname[15]; int statarray[15]; int starttime[2]; }; static struct proctbl procs[1000]; static char *namtbl[] = { "PWRK$MASTER", "PWRK$LMSRV", "PWRK$LMMCP", "PWRK$LMDMN", "PWRK$ADMIN_0", "PWRK$LICENSE_R", "PWRK$KNBDAEMON", "PWRK$NBDAEMON", "PWRK$MONITOR", "NETBIOS", "" }; int procinit() { struct proctbl *p; char **namp; int stat, starttime[2]; if (sch$gl_maxpix > 1000) return (SS$_INSFMEM); stat = sys$gettim(starttime); if (stat & 1) { namp = namtbl; p = procs; for (; *namp[0]; p++, namp++) { p_strcpy(p->procname,*namp); p->proclen = p_strlen(p->procname); p_bzero(p->statarray,sizeof(p->statarray)); p->starttime[0] = starttime[0]; p->starttime[1] = starttime[1]; } p->proclen = 0; } return stat; } int procproc() { unsigned int maxindex, *tblpnt; PCB *pcbpnt, *nullpcb; struct proctbl *p; int j, namesize; maxindex = sch$gl_maxpix - 2; tblpnt = (unsigned int *) sch$gl_pcbvec; nullpcb = (PCB *) *tblpnt++; /* pcb of null process */ tblpnt++; /* skip swapper */ for (j = 0; j <= maxindex; j++) { pcbpnt = (PCB *) *tblpnt++; if (pcbpnt != nullpcb) { namesize = *pcbpnt->pcb$t_lname & 0xff; for (p = procs; p->proclen > 0; p++) { if ((p->proclen == namesize) && (p_strncmp(pcbpnt->pcb$t_lname+1,p->procname,namesize) == 0)) { #ifdef ALPHA p->statarray[pcbpnt->pcb$l_state]++; #else p->statarray[pcbpnt->pcb$w_state]++; #endif } } } } return 1; } int p_strncmp(s1, s2, n) register unsigned char *s1, *s2; register n; { while (--n >= 0 && *s1 == *s2++) if (*s1++ == '\0') return(0); return(n<0 ? 0 : *s1 - *--s2); } char *p_strcpy(s1, s2) register char *s1, *s2; { register char *os1; os1 = s1; while (*s1++ = *s2++); return(os1); } int p_strlen(s) register char *s; { register n; n = 0; while (*s++) n++; return(n); } void p_bzero(p, n) register char *p; register n; { while (--n >= 0) *p++ = 0; } | |||||
1832.15 | More info | UTRTSC::VDBURG | Change mode to PANIC | Thu Mar 27 1997 04:50 | 6 |
I found some reference to the unload problem: I link in the module SYS$DOINIT from STARLET.OLB, but for real dynamic unloading SYS$DOINIT_UNL is needed which is not provided. Jur. |