/* PL/I symbolic debugger module to handle module-related commands */ modcmd: procedure; %include 'putdef.pli'; %include 'scandef.pli'; %include 'workdef.pli'; %include 'segdef.pli'; %include 'symdef.pli'; %include 'moddef.pli'; %include 'initdef.pli'; %include 'cantopen.inc'; %include 'prologn.inc'; %include 'symswitch.inc'; %include 'readsym.inc'; %include 'external.inc'; /* symfile header definitions: */ dcl 1 symfile_blockrecord(16) static, /*static so comes out of overlay space rather than auto space, which is in root*/ 2 vsymaddr fixed bin(15), 2 pad(3) fixed bin(15); dcl psymfile_record pointer initial(addr(symfile_blockrecord)); dcl 1 symfile_firstrecord /*defined(symfile_blockrecord)*/ based(psymfile_record), 2 basesymaddr fixed bin(15), 2 endsymaddr fixed bin(15), 2 firstsymaddr fixed bin(15); dcl symfile_headersize fixed bin(15) static initial('1200'B3), /*aggregate size of all the header records in symbol table*/ symfile_recsize fixed bin(15) static initial(128); dcl module char(30) varying static initial(' MODULES MODULE MODU MOD '), /*MODU is minimum abbreviation on VAX, so we must allow*/ modulename char(31) varying, modulename6 char(6) varying, symname char(31) varying, newsymfilename char(35) varying, modulesegment fixed bin(23), symfilepos fixed bin(23), blocksymaddr fixed bin(15), iblock fixed bin(15), first_block fixed bin(1), found_external fixed bin(1), more_to_show fixed bin(1), ttype fixed bin(7), t fixed bin(7), (i,j,x) fixed bin(15), /*scratch*/ oncode builtin; /**************************************************************************************************************/ if nxtokenis(module) /*SET keyword has been factored out*/ then do; setmod_next: call segment(modulesegment); /*parse optional overlay segment specification*/ modulename = nxsymtoken; modulename6 = modulename; if debprocedure_define_level ^= 0 then goto setmod_done; call symswitch(setting_module); /*free up current_module record*/ found_external = false; if ^ initializing then do; find_external: /*normal SET MODULE - look up the external in the map*/ if workget(modulename6, module_class, any_parent, scratch_workp) then call error('SET MODULE has already been done for a module of this name'); current_module.prolog = external_address(modulename6, external_procedure_class, modulesegment); if current_module.prolog = not_found then call error('external procedure not found'); found_external = true; current_module.name = modulename6; t = workget(modulename6, external_procedure_class, any_parent, scratch_workp); /*get the hash record*/ call workread(symname, scratch_workp); /*symfile name follows*/ call workgrab(scratch_workp->workbuf.parent, scratch_workp); /*get the overlay record*/ current_module.overlay = scratch_workp->workbuf.value; /*overlay segment descriptor address*/ current_module.overlay_fileaddr = scratch_workp->workbuf.fileaddr; /*overlay segment hash record fileaddr*/ current_module.overlay_name = scratch_workp->workbuf.name; /*overlay segment name ***in case needed*/ end; else do; /*initialization - short cut to save time*/ current_module.prolog = main_address; /*address of main procedure*/ current_module.name = prologname(main_address); symname = modulename; /*actually the program name (assume same as main procedure name for short cut)*/ modulename = current_module.name; /*set to main procedure name (6 chars) for open retry in case not the same*/ current_module.overlay = root_segment_descriptor; /*segment procedure has ensured this is initialized*/ current_module.overlay_fileaddr = root_segment_fileaddr; current_module.overlay_name = root_segment_name; /***in case needed**/ end; open_symfile: newsymfilename = uic_file_prefix!!symname!!'.SYM'; if newsymfilename ^= current_module.symfilename then do; close file(symfile); on undefinedfile(symfile) begin; current_module.symfilename = ''; if ^ found_external then do; modulename6 = current_module.name; goto find_external; /*initialization short cut didnt work, look it up*/ end; if symname ^= modulename /*if objectname.SYM not found try modulename.SYM (allows debugging modules in libraries)*/ then do; symname = modulename; goto open_symfile; end; call error(cantopen(newsymfilename,oncode)); end; open file(symfile) title(newsymfilename); current_module.symfilename = newsymfilename; end; on endfile(symfile) begin; close file(symfile); current_module.symfilename = ''; call error('symbol table for this module not found in '!!newsymfilename); end; symfile_module_base = 0; do while(true); /*step through concatenated symbol tables, looking for the one matching desired module*/ call posfile(symfile, symfile_module_base); read file(symfile) into(symfile_blockrecord); symfile_base = symfile_firstrecord.basesymaddr; symfile_end = symfile_firstrecord.endsymaddr; symfile_offset = symfile_base - (symfile_headersize - symbolheadersize); symfile_first = symfile_firstrecord.firstsymaddr; symfile_next = symfile_first; symfilepos = current_fileaddr(symfile); first_block = true; iblock = 0; do i = 1 to 4; call posfile(symfile, symfilepos); read file(symfile) into(symfile_blockrecord); symfilepos = current_fileaddr(symfile); do j = 1 to hbound(symfile_blockrecord,1); current_module.blocks(iblock).name6 = ''; /*set only so can see how far got with wk command*/ blocksymaddr = symfile_blockrecord(j).vsymaddr; if blocksymaddr = 0 then goto setmod_done; call read_symbol(blocksymaddr, scratch_symp); if first_block then do; modulename6 = scratch_symp->symbol.name; if current_module.name ^= modulename6 then goto next_module; put_workp->workbuf.value = current_module.prolog; call workput(current_module.name, module_class, current_module.overlay_fileaddr); current_module.hash_fileaddr = put_workp->workbuf.fileaddr; current_module.data_fileaddr = current_fileaddr(workfile); if initializing then default_module = current_module.hash_fileaddr; write file(workfile) from(current_module); any_symscan = true; /*must write out block table*/ block_data.parent = null_fileaddr; block_data.address = current_module.prolog; /*symbol.offset not valid for external procedure*/ end; else do; block_data.parent = current_module.blocks(scratch_symp->symbol.actual_block_code).fileaddr; block_data.address = current_module.prolog + scratch_symp->symbol.offset; end; block_data.symaddr = blocksymaddr; put_workp->workbuf.value = iblock; /*block code*/ call workput(scratch_symp->symbol.name, block_class, current_module.hash_fileaddr); if first_block then do; last_block = put_workp->workbuf.fileaddr; /*allow set break \nnn after set mod*/ if initializing then default_block = last_block; end; write file(workfile) from(block_data); current_module.blocks(iblock).fileaddr = put_workp->workbuf.fileaddr; current_module.blocks(iblock).name6 = scratch_symp->symbol.name; current_module.blocks(iblock).parent = scratch_symp->symbol.actual_block_code; current_module.blocks(iblock).address = block_data.address; iblock = iblock + 1; first_block = false; end; end; goto setmod_next; next_module: symfile_module_base = symfile_module_base + ( (symfile_end - symfile_base + symfile_headersize) + symfile_recsize-1 ) /symfile_recsize*symfile_recsize; end /*of step through concatenated symbol tables loop*/; setmod_done: if nxtokenis(';') then goto command_done; t = nxtokenis(','); /*might as well make commas optional*/ goto setmod_next; /*loop, stepping through list of modules user specified in command*/ end/*SET MODULE*/; if nxtokenis(show) then if nxtokenis(module) then do; call endscan; call put_skip_list('symbolic access has been established (via SET MODULE) for the following modules:'); more_to_show = workget(any_name, module_class, any_parent, path_workp); /*empty list cant happen, since initialization automatically sets module to main*/ do while(more_to_show); if user_is_overlaid then do; call workgrab(path_workp->workbuf.parent, scratch_workp); /*get the overlay record*/ call put_list(scratch_workp->workbuf.name, '\'); /*overlay segment name*/ end; call put_list(path_workp->workbuf.name, ' '); /*put list automatically wraps*/ more_to_show = worknext(any_name, module_class, any_parent, path_workp); end; goto command_done; end/*SHOW MODULE*/; nextp = startp; return; command_done: signal condition(endcmd); end;