vms.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572
  1. /* vms.c -- Write out a VAX/VMS object file
  2. Copyright (C) 1987, 1988 David L. Kashtan and Free Software Foundation, Inc.
  3. This file is part of GAS, the GNU Assembler.
  4. GAS is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8. GAS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GAS; see the file COPYING. If not, write to
  14. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include "as.h"
  18. #include "md.h"
  19. #include "subsegs.h"
  20. #include "obstack.h"
  21. #include "struc-symbol.h"
  22. #include "write.h"
  23. #include "symbols.h"
  24. #ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
  25. #include <stab.h>
  26. #include "objrecdef.h" /* Define VMS Object record lang. */
  27. #include <vms/fabdef.h> /* Define File Access Block */
  28. #include <vms/namdef.h> /* Define NAM Block */
  29. #include <vms/xabdef.h> /* Define XAB */
  30. #include <vms/xabdatdef.h> /* Define Date XAB */
  31. #include <vms/xabfhcdef.h> /* Define File Header XAB */
  32. /*
  33. * Version string of the compiler that produced the code we are
  34. * assembling.
  35. */
  36. char *compiler_version_string;
  37. static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
  38. /*
  39. * We augment the "gas" symbol structure with this
  40. */
  41. struct VMS_Symbol {
  42. struct VMS_Symbol *Next;
  43. struct symbol *Symbol;
  44. int Size;
  45. int Psect_Index;
  46. int Psect_Offset;
  47. };
  48. static struct VMS_Symbol *VMS_Symbols = 0;
  49. /*
  50. * If the procedure "main()" exists we have to add the instruction
  51. * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
  52. */
  53. VMS_Check_For_Main()
  54. {
  55. register symbolS *symbolP;
  56. #ifdef HACK_DEC_C_STARTUP
  57. register struct frchain *frchainP;
  58. register fragS *fragP;
  59. register fragS **prev_fragPP;
  60. register struct fix *fixP;
  61. register fragS *New_Frag;
  62. int i;
  63. #endif HACK_DEC_C_STARTUP
  64. symbolP = (struct symbol *)symbol_find("_main");
  65. if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
  66. #ifndef HACK_DEC_C_STARTUP
  67. /*
  68. * Remember the entry point symbol
  69. */
  70. Entry_Point_Symbol = symbolP;
  71. #else HACK_DEC_C_STARTUP
  72. /*
  73. * Scan all the fragment chains for the one with "_main"
  74. * (Actually we know the fragment from the symbol, but we need
  75. * the previous fragment so we can change its pointer)
  76. */
  77. frchainP = frchain_root;
  78. while(frchainP) {
  79. /*
  80. * Scan all the fragments in this chain, remembering
  81. * the "previous fragment"
  82. */
  83. prev_fragPP = &frchainP->frch_root;
  84. fragP = frchainP->frch_root;
  85. while(fragP && (fragP != frchainP->frch_last)) {
  86. /*
  87. * Is this the fragment?
  88. */
  89. if (fragP == symbolP->sy_frag) {
  90. /*
  91. * Yes: Modify the fragment by replacing
  92. * it with a new fragment.
  93. */
  94. New_Frag = (fragS *)
  95. xmalloc(sizeof(*New_Frag) +
  96. fragP->fr_fix +
  97. fragP->fr_var +
  98. 5);
  99. /*
  100. * The fragments are the same except
  101. * that the "fixed" area is larger
  102. */
  103. *New_Frag = *fragP;
  104. New_Frag->fr_fix += 6;
  105. /*
  106. * Copy the literal data opening a hole
  107. * 2 bytes after "_main" (i.e. just after
  108. * the entry mask). Into which we place
  109. * the JSB instruction.
  110. */
  111. New_Frag->fr_literal[0] = fragP->fr_literal[0];
  112. New_Frag->fr_literal[1] = fragP->fr_literal[1];
  113. New_Frag->fr_literal[2] = 0x16; /* Jsb */
  114. New_Frag->fr_literal[3] = 0xef;
  115. New_Frag->fr_literal[4] = 0;
  116. New_Frag->fr_literal[5] = 0;
  117. New_Frag->fr_literal[6] = 0;
  118. New_Frag->fr_literal[7] = 0;
  119. for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
  120. New_Frag->fr_literal[i+6] =
  121. fragP->fr_literal[i];
  122. /*
  123. * Now replace the old fragment with the
  124. * newly generated one.
  125. */
  126. *prev_fragPP = New_Frag;
  127. /*
  128. * Remember the entry point symbol
  129. */
  130. Entry_Point_Symbol = symbolP;
  131. /*
  132. * Scan the text area fixup structures
  133. * as offsets in the fragment may have
  134. * changed
  135. */
  136. for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
  137. /*
  138. * Look for references to this
  139. * fragment.
  140. */
  141. if (fixP->fx_frag == fragP) {
  142. /*
  143. * Change the fragment
  144. * pointer
  145. */
  146. fixP->fx_frag = New_Frag;
  147. /*
  148. * If the offset is after
  149. * the entry mask we need
  150. * to account for the JSB
  151. * instruction we just
  152. * inserted.
  153. */
  154. if (fixP->fx_where >= 2)
  155. fixP->fx_where += 6;
  156. }
  157. }
  158. /*
  159. * Scan the symbols as offsets in the
  160. * fragment may have changed
  161. */
  162. for(symbolP = symbol_rootP;
  163. symbolP;
  164. symbolP = symbolP->sy_next) {
  165. /*
  166. * Look for references to this
  167. * fragment.
  168. */
  169. if (symbolP->sy_frag == fragP) {
  170. /*
  171. * Change the fragment
  172. * pointer
  173. */
  174. symbolP->sy_frag = New_Frag;
  175. /*
  176. * If the offset is after
  177. * the entry mask we need
  178. * to account for the JSB
  179. * instruction we just
  180. * inserted.
  181. */
  182. if (symbolP->sy_nlist.n_value >= 2)
  183. symbolP->sy_nlist.n_value += 6;
  184. }
  185. }
  186. /*
  187. * Make a symbol reference to
  188. * "_c$main_args" so we can get
  189. * its address inserted into the
  190. * JSB instruction.
  191. */
  192. symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
  193. symbolP->sy_nlist.n_un.n_name = "_c$main_args";
  194. symbolP->sy_nlist.n_type = N_UNDF;
  195. symbolP->sy_nlist.n_other = 0;
  196. symbolP->sy_nlist.n_desc = 0;
  197. symbolP->sy_nlist.n_value = 0;
  198. symbolP->sy_name_offset = 0;
  199. symbolP->sy_number = 0;
  200. symbolP->sy_frag = New_Frag;
  201. symbolP->sy_forward = 0;
  202. symbolP->sy_next = symbol_rootP;
  203. symbol_rootP = symbolP;
  204. /*
  205. * Generate a text fixup structure
  206. * to get "_c$main_args" stored into the
  207. * JSB instruction.
  208. */
  209. fixP = (struct fix *)xmalloc(sizeof(*fixP));
  210. fixP->fx_frag = New_Frag;
  211. fixP->fx_where = 4;
  212. fixP->fx_addsy = symbolP;
  213. fixP->fx_subsy = 0;
  214. fixP->fx_offset = 0;
  215. fixP->fx_size = sizeof(long);
  216. fixP->fx_pcrel = 1;
  217. fixP->fx_next = text_fix_root;
  218. text_fix_root = fixP;
  219. /*
  220. * Now make sure we exit from the loop
  221. */
  222. frchainP = 0;
  223. break;
  224. }
  225. /*
  226. * Try the next fragment
  227. */
  228. prev_fragPP = &fragP->fr_next;
  229. fragP = fragP->fr_next;
  230. }
  231. /*
  232. * Try the next fragment chain
  233. */
  234. if (frchainP) frchainP=frchainP->frch_next;
  235. }
  236. #endif HACK_DEC_C_STARTUP
  237. }
  238. }
  239. /*
  240. * Write a VAX/VMS object file (everything else has been done!)
  241. */
  242. VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
  243. unsigned text_siz;
  244. unsigned data_siz;
  245. struct frag *text_frag_root;
  246. struct frag *data_frag_root;
  247. {
  248. register fragS * fragP;
  249. register symbolS * symbolP;
  250. register symbolS * sp;
  251. register struct fix * fixP;
  252. register struct VMS_Symbol * vsp;
  253. int Local_Initialized_Data_Size = 0;
  254. int Psect_Number = 0; /* Psect Index Number */
  255. int Text_Psect = -1; /* Text Psect Index */
  256. int Data_Psect = -1; /* Data Psect Index */
  257. int Bss_Psect = -1; /* Bss Psect Index */
  258. /*
  259. * Create the VMS object file
  260. */
  261. Create_VMS_Object_File();
  262. /*
  263. * Write the module header records
  264. */
  265. Write_VMS_MHD_Records();
  266. /*
  267. * Generate the VMS object file records
  268. * 1st GSD then TIR records
  269. */
  270. /******* Global Symbol Dictionary *******/
  271. /*
  272. * Define the Text Psect
  273. */
  274. if (text_siz > 0) {
  275. Text_Psect = Psect_Number++;
  276. VMS_Psect_Spec("$code",text_siz,"TEXT");
  277. }
  278. /*
  279. * Define the BSS Psect
  280. */
  281. if (local_bss_counter > 0) {
  282. Bss_Psect = Psect_Number++;
  283. VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
  284. }
  285. /*
  286. * Now scan the symbols and emit the appropriate GSD records
  287. */
  288. for (sp = symbol_rootP; sp; sp = sp->sy_next) {
  289. /*
  290. * Dispatch on symbol type
  291. */
  292. switch(sp->sy_type) {
  293. /*
  294. * Global uninitialized data
  295. */
  296. case N_UNDF | N_EXT:
  297. /*
  298. * Make a VMS data symbol entry
  299. */
  300. vsp = (struct VMS_Symbol *)
  301. xmalloc(sizeof(*vsp));
  302. vsp->Symbol = sp;
  303. vsp->Size = sp->sy_nlist.n_value;
  304. vsp->Psect_Index = Psect_Number++;
  305. vsp->Psect_Offset = 0;
  306. vsp->Next = VMS_Symbols;
  307. VMS_Symbols = vsp;
  308. sp->sy_number = (int)vsp;
  309. /*
  310. * Make the psect for this data
  311. */
  312. VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  313. vsp->Size,
  314. "COMMON");
  315. #ifdef NOT_VAX_11_C_COMPATIBLE
  316. /*
  317. * Place a global symbol at the
  318. * beginning of the Psect
  319. */
  320. VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  321. vsp->Psect_Index,
  322. 0,
  323. 1);
  324. #endif NOT_VAX_11_C_COMPATIBLE
  325. break;
  326. /*
  327. * Local uninitialized data
  328. */
  329. case N_BSS:
  330. /*
  331. * Make a VMS data symbol entry
  332. */
  333. vsp = (struct VMS_Symbol *)
  334. xmalloc(sizeof(*vsp));
  335. vsp->Symbol = sp;
  336. vsp->Size = 0;
  337. vsp->Psect_Index = Bss_Psect;
  338. vsp->Psect_Offset =
  339. sp->sy_nlist.n_value -
  340. bss_address_frag . fr_address;
  341. vsp->Next = VMS_Symbols;
  342. VMS_Symbols = vsp;
  343. sp->sy_number = (int)vsp;
  344. break;
  345. /*
  346. * Global initialized data
  347. */
  348. case N_DATA | N_EXT:
  349. /*
  350. * Make a VMS data symbol entry
  351. */
  352. vsp = (struct VMS_Symbol *)
  353. xmalloc(sizeof(*vsp));
  354. vsp->Symbol = sp;
  355. vsp->Size = VMS_Initialized_Data_Size(sp,
  356. text_siz + data_siz);
  357. vsp->Psect_Index = Psect_Number++;
  358. vsp->Psect_Offset = 0;
  359. vsp->Next = VMS_Symbols;
  360. VMS_Symbols = vsp;
  361. sp->sy_number = (int)vsp;
  362. /*
  363. * Make its psect
  364. */
  365. VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  366. vsp->Size,
  367. "COMMON");
  368. #ifdef NOT_VAX_11_C_COMPATIBLE
  369. /*
  370. * Place a global symbol at the
  371. * beginning of the Psect
  372. */
  373. VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  374. vsp->Psect_Index,
  375. 0,
  376. 1);
  377. #endif NOT_VAX_11_C_COMPATIBLE
  378. break;
  379. /*
  380. * Local initialized data
  381. */
  382. case N_DATA:
  383. /*
  384. * Make a VMS data symbol entry
  385. */
  386. vsp = (struct VMS_Symbol *)
  387. xmalloc(sizeof(*vsp));
  388. vsp->Symbol = sp;
  389. vsp->Size =
  390. VMS_Initialized_Data_Size(sp,
  391. text_siz + data_siz);
  392. vsp->Psect_Index = Data_Psect;
  393. vsp->Psect_Offset =
  394. Local_Initialized_Data_Size;
  395. Local_Initialized_Data_Size += vsp->Size;
  396. vsp->Next = VMS_Symbols;
  397. VMS_Symbols = vsp;
  398. sp->sy_number = (int)vsp;
  399. break;
  400. /*
  401. * Global Text definition
  402. */
  403. case N_TEXT | N_EXT: {
  404. unsigned short Entry_Mask;
  405. /*
  406. * Get the entry mask
  407. */
  408. fragP = sp->sy_frag;
  409. Entry_Mask = (fragP->fr_literal[0] & 0xff) +
  410. ((fragP->fr_literal[1] & 0xff)
  411. << 8);
  412. /*
  413. * Define the Procedure entry pt.
  414. */
  415. VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
  416. Text_Psect,
  417. sp->sy_nlist.n_value,
  418. Entry_Mask);
  419. break;
  420. }
  421. /*
  422. * Local Text definition
  423. */
  424. case N_TEXT:
  425. /*
  426. * Make a VMS data symbol entry
  427. */
  428. vsp = (struct VMS_Symbol *)
  429. xmalloc(sizeof(*vsp));
  430. vsp->Symbol = sp;
  431. vsp->Size = 0;
  432. vsp->Psect_Index = Text_Psect;
  433. vsp->Psect_Offset = sp->sy_nlist.n_value;
  434. vsp->Next = VMS_Symbols;
  435. VMS_Symbols = vsp;
  436. sp->sy_number = (int)vsp;
  437. break;
  438. /*
  439. * Global Reference
  440. */
  441. case N_UNDF:
  442. /*
  443. * Make a GSD global symbol reference
  444. * record.
  445. */
  446. VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  447. 0,
  448. 0,
  449. 0);
  450. break;
  451. /*
  452. * Anything else
  453. */
  454. default:
  455. /*
  456. * Ignore STAB symbols
  457. */
  458. if ((sp->sy_type & N_STAB) != 0) break;
  459. /*
  460. * Error
  461. */
  462. printf(" ERROR, unknown type (%d)\n",
  463. sp->sy_nlist.n_type);
  464. break;
  465. }
  466. }
  467. /*
  468. * Define the Data Psect
  469. */
  470. if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
  471. /*
  472. * Do it
  473. */
  474. Data_Psect = Psect_Number++;
  475. VMS_Psect_Spec("$data",
  476. Local_Initialized_Data_Size,
  477. "DATA");
  478. /*
  479. * Scan the VMS symbols and fill in the data psect
  480. */
  481. for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  482. /*
  483. * Only look for undefined psects
  484. */
  485. if (vsp->Psect_Index < 0) {
  486. /*
  487. * And only initialized data
  488. */
  489. if (vsp->Symbol->sy_nlist.n_type == N_DATA)
  490. vsp->Psect_Index = Data_Psect;
  491. }
  492. }
  493. }
  494. /******* Text Information and Relocation Records *******/
  495. /*
  496. * Write the text segment data
  497. */
  498. if (text_siz > 0) {
  499. /*
  500. * Scan the text fragments
  501. */
  502. for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  503. /*
  504. * Stop if we get to the data fragments
  505. */
  506. if (fragP == data_frag_root) break;
  507. /*
  508. * Ignore fragments with no data
  509. */
  510. if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
  511. continue;
  512. /*
  513. * Go the the appropriate offset in the
  514. * Text Psect.
  515. */
  516. VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
  517. /*
  518. * Store the "fixed" part
  519. */
  520. if (fragP->fr_fix)
  521. VMS_Store_Immediate_Data(fragP->fr_literal,
  522. fragP->fr_fix,
  523. OBJ$C_TIR);
  524. /*
  525. * Store the "variable" part
  526. */
  527. if (fragP->fr_var && fragP->fr_offset)
  528. VMS_Store_Repeated_Data(fragP->fr_offset,
  529. fragP->fr_literal+
  530. fragP->fr_fix,
  531. fragP->fr_var,
  532. OBJ$C_TIR);
  533. }
  534. /*
  535. * Now we go through the text segment fixups and
  536. * generate TIR records to fix up addresses within
  537. * the Text Psect
  538. */
  539. for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
  540. /*
  541. * We DO handle the case of "Symbol - Symbol" as
  542. * long as it is in the same segment.
  543. */
  544. if (fixP->fx_subsy && fixP->fx_addsy) {
  545. int i;
  546. /*
  547. * They need to be in the same segment
  548. */
  549. if (fixP->fx_subsy->sy_type !=
  550. fixP->fx_addsy->sy_type)
  551. error("Fixup data addsy and subsy didn't have the same type");
  552. /*
  553. * And they need to be in one that we
  554. * can check the psect on
  555. */
  556. if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
  557. ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
  558. error("Fixup data addsy and subsy didn't have an appropriate type");
  559. /*
  560. * This had better not be PC relative!
  561. */
  562. if (fixP->fx_pcrel)
  563. error("Fixup data was erroneously \"pcrel\"");
  564. /*
  565. * Subtract their values to get the
  566. * difference.
  567. */
  568. i = fixP->fx_addsy->sy_value -
  569. fixP->fx_subsy->sy_value;
  570. /*
  571. * Now generate the fixup object records
  572. * Set the psect and store the data
  573. */
  574. VMS_Set_Psect(Text_Psect,
  575. fixP->fx_where +
  576. fixP->fx_frag->fr_address,
  577. OBJ$C_TIR);
  578. VMS_Store_Immediate_Data(&i,
  579. fixP->fx_size,
  580. OBJ$C_TIR);
  581. /*
  582. * Done
  583. */
  584. continue;
  585. }
  586. /*
  587. * Size will HAVE to be "long"
  588. */
  589. if (fixP->fx_size != sizeof(long))
  590. error("Fixup datum was not a longword");
  591. /*
  592. * Symbol must be "added" (if it is ever
  593. * subtracted we can
  594. * fix this assumption)
  595. */
  596. if (fixP->fx_addsy == 0)
  597. error("Fixup datum was not \"fixP->fx_addsy\"");
  598. /*
  599. * Store the symbol value in a PIC fashion
  600. */
  601. VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
  602. fixP->fx_offset,
  603. fixP->fx_pcrel,
  604. Text_Psect,
  605. fixP->fx_where +
  606. fixP->fx_frag->fr_address,
  607. OBJ$C_TIR);
  608. /*
  609. * Check for indirect address reference,
  610. * which has to be fixed up (as the linker
  611. * will screw it up with TIR$C_STO_PICR).
  612. */
  613. if (fixP->fx_pcrel)
  614. VMS_Fix_Indirect_Reference(Text_Psect,
  615. fixP->fx_where +
  616. fixP->fx_frag->fr_address,
  617. fixP->fx_frag,
  618. text_frag_root);
  619. }
  620. }
  621. /*
  622. * Store the Data segment:
  623. *
  624. * Since this is REALLY hard to do any other way,
  625. * we actually manufacture the data segment and
  626. * the store the appropriate values out of it.
  627. */
  628. if (data_siz > 0) {
  629. char *Data_Segment;
  630. /*
  631. * Allocate the data segment
  632. */
  633. Data_Segment = (char *)xmalloc(data_siz);
  634. /*
  635. * Run through the data fragments, filling in the segment
  636. */
  637. for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
  638. register long int count;
  639. register char * fill_literal;
  640. register long int fill_size;
  641. int i;
  642. i = fragP->fr_address - text_siz;
  643. if (fragP->fr_fix)
  644. bcopy(fragP->fr_literal,
  645. Data_Segment + i,
  646. fragP->fr_fix);
  647. i += fragP->fr_fix;
  648. fill_literal= fragP -> fr_literal + fragP -> fr_fix;
  649. fill_size = fragP -> fr_var;
  650. for (count = fragP -> fr_offset; count; count --) {
  651. if (fill_size)
  652. bcopy(fill_literal,
  653. Data_Segment + i,
  654. fill_size);
  655. i += fill_size;
  656. }
  657. }
  658. /*
  659. * Now we can run through all the data symbols
  660. * and store the data
  661. */
  662. for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  663. /*
  664. * Ignore anything other than data symbols
  665. */
  666. if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
  667. continue;
  668. /*
  669. * Set the Psect + Offset
  670. */
  671. VMS_Set_Psect(vsp->Psect_Index,
  672. vsp->Psect_Offset,
  673. OBJ$C_TIR);
  674. /*
  675. * Store the data
  676. */
  677. VMS_Store_Immediate_Data(Data_Segment +
  678. vsp->Symbol->sy_nlist.n_value -
  679. text_siz,
  680. vsp->Size,
  681. OBJ$C_TIR);
  682. }
  683. /*
  684. * Now we go through the data segment fixups and
  685. * generate TIR records to fix up addresses within
  686. * the Data Psects
  687. */
  688. for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
  689. /*
  690. * Find the symbol for the containing datum
  691. */
  692. for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  693. /*
  694. * Only bother with Data symbols
  695. */
  696. sp = vsp->Symbol;
  697. if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
  698. continue;
  699. /*
  700. * Ignore symbol if After fixup
  701. */
  702. if (sp->sy_nlist.n_value >
  703. (fixP->fx_where +
  704. fixP->fx_frag->fr_address))
  705. continue;
  706. /*
  707. * See if the datum is here
  708. */
  709. if ((sp->sy_nlist.n_value + vsp->Size) <=
  710. (fixP->fx_where +
  711. fixP->fx_frag->fr_address))
  712. continue;
  713. /*
  714. * We DO handle the case of "Symbol - Symbol" as
  715. * long as it is in the same segment.
  716. */
  717. if (fixP->fx_subsy && fixP->fx_addsy) {
  718. int i;
  719. /*
  720. * They need to be in the same segment
  721. */
  722. if (fixP->fx_subsy->sy_type !=
  723. fixP->fx_addsy->sy_type)
  724. error("Fixup data addsy and subsy didn't have the same type");
  725. /*
  726. * And they need to be in one that we
  727. * can check the psect on
  728. */
  729. if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
  730. ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
  731. error("Fixup data addsy and subsy didn't have an appropriate type");
  732. /*
  733. * This had better not be PC relative!
  734. */
  735. if (fixP->fx_pcrel)
  736. error("Fixup data was erroneously \"pcrel\"");
  737. /*
  738. * Subtract their values to get the
  739. * difference.
  740. */
  741. i = fixP->fx_addsy->sy_value -
  742. fixP->fx_subsy->sy_value;
  743. /*
  744. * Now generate the fixup object records
  745. * Set the psect and store the data
  746. */
  747. VMS_Set_Psect(vsp->Psect_Index,
  748. fixP->fx_frag->fr_address +
  749. fixP->fx_where -
  750. vsp->Symbol->sy_value +
  751. vsp->Psect_Offset,
  752. OBJ$C_TIR);
  753. VMS_Store_Immediate_Data(&i,
  754. fixP->fx_size,
  755. OBJ$C_TIR);
  756. /*
  757. * Done
  758. */
  759. break;
  760. }
  761. /*
  762. * Size will HAVE to be "long"
  763. */
  764. if (fixP->fx_size != sizeof(long))
  765. error("Fixup datum was not a longword");
  766. /*
  767. * Symbol must be "added" (if it is ever
  768. * subtracted we can
  769. * fix this assumption)
  770. */
  771. if (fixP->fx_addsy == 0)
  772. error("Fixup datum was not \"fixP->fx_addsy\"");
  773. /*
  774. * Store the symbol value in a PIC fashion
  775. */
  776. VMS_Store_PIC_Symbol_Reference(
  777. fixP->fx_addsy,
  778. fixP->fx_offset,
  779. fixP->fx_pcrel,
  780. vsp->Psect_Index,
  781. fixP->fx_frag->fr_address +
  782. fixP->fx_where -
  783. vsp->Symbol->sy_value +
  784. vsp->Psect_Offset,
  785. OBJ$C_TIR);
  786. /*
  787. * Done
  788. */
  789. break;
  790. }
  791. }
  792. }
  793. /*
  794. * Write the Traceback Begin Module record
  795. */
  796. VMS_TBT_Module_Begin();
  797. /*
  798. * Scan the symbols and write out the routines
  799. * (this makes the assumption that symbols are in
  800. * order of ascending text segment offset)
  801. */
  802. {
  803. struct symbol *Current_Routine = 0;
  804. int Current_Line_Number = 0;
  805. int Current_Offset = -1;
  806. int Has_Source_File = 0;
  807. int Largest_Line_Number = 0;
  808. for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) {
  809. /*
  810. * Deal with text symbols
  811. */
  812. if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
  813. /*
  814. * Ignore symbols starting with "L",
  815. * as they are local symbols
  816. */
  817. if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
  818. /*
  819. * If there is a routine start defined,
  820. * terminate it.
  821. */
  822. if (Current_Routine) {
  823. /*
  824. * End the routine
  825. */
  826. VMS_TBT_Routine_End(
  827. symbolP->sy_nlist.n_value -
  828. Current_Routine->sy_nlist.n_value);
  829. }
  830. /*
  831. * Store the routine begin traceback info
  832. */
  833. VMS_TBT_Routine_Begin(symbolP,Text_Psect);
  834. Current_Routine = symbolP;
  835. /*
  836. * Done
  837. */
  838. continue;
  839. }
  840. /*
  841. * Deal with STAB symbols
  842. */
  843. if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
  844. /*
  845. * Dispatch on STAB type
  846. */
  847. switch(symbolP->sy_nlist.n_type) {
  848. /*
  849. * Line number
  850. */
  851. case N_SLINE:
  852. /*
  853. * If this is the 1st N_SLINE, setup
  854. * PC/Line correlation. Otherwise
  855. * do the delta PC/Line. If the offset
  856. * for the line number is not +ve we need
  857. * to do another PC/Line correlation
  858. * setup
  859. */
  860. if (Current_Offset == -1) {
  861. VMS_TBT_Line_PC_Correlation(
  862. symbolP->sy_nlist.n_desc,
  863. symbolP->sy_nlist.n_value,
  864. Text_Psect,
  865. 0);
  866. } else {
  867. if ((symbolP->sy_nlist.n_desc -
  868. Current_Line_Number) <= 0) {
  869. /*
  870. * Line delta is not +ve, we
  871. * need to close the line and
  872. * start a new PC/Line
  873. * correlation.
  874. */
  875. VMS_TBT_Line_PC_Correlation(0,
  876. symbolP->sy_nlist.n_value -
  877. Current_Offset,
  878. 0,
  879. -1);
  880. VMS_TBT_Line_PC_Correlation(
  881. symbolP->sy_nlist.n_desc,
  882. symbolP->sy_nlist.n_value,
  883. Text_Psect,
  884. 0);
  885. } else {
  886. /*
  887. * Line delta is +ve, all is well
  888. */
  889. VMS_TBT_Line_PC_Correlation(
  890. symbolP->sy_nlist.n_desc -
  891. Current_Line_Number,
  892. symbolP->sy_nlist.n_value -
  893. Current_Offset,
  894. 0,
  895. 1);
  896. }
  897. }
  898. /*
  899. * Update the current line/PC
  900. */
  901. Current_Line_Number = symbolP->sy_nlist.n_desc;
  902. if (Current_Line_Number > Largest_Line_Number)
  903. Largest_Line_Number =
  904. Current_Line_Number;
  905. Current_Offset = symbolP->sy_nlist.n_value;
  906. /*
  907. * Done
  908. */
  909. break;
  910. /*
  911. * Source file
  912. */
  913. case N_SO:
  914. /*
  915. * Remember that we had a source file
  916. * and emit the source file debugger
  917. * record
  918. */
  919. Has_Source_File =
  920. VMS_TBT_Source_File(
  921. symbolP->sy_nlist.n_un.n_name,
  922. 1);
  923. break;
  924. }
  925. }
  926. }
  927. /*
  928. * If there is a routine start defined,
  929. * terminate it (and the line numbers)
  930. */
  931. if (Current_Routine) {
  932. /*
  933. * Terminate the line numbers
  934. */
  935. VMS_TBT_Line_PC_Correlation(0,
  936. text_siz - Current_Routine->sy_nlist.n_value,
  937. 0,
  938. -1);
  939. /*
  940. * If there is a source file write out the number
  941. * of source lines to correlate
  942. */
  943. if (Has_Source_File)
  944. VMS_TBT_Source_Lines(Largest_Line_Number);
  945. /*
  946. * Terminate the routine
  947. */
  948. VMS_TBT_Routine_End(text_siz -
  949. Current_Routine->sy_nlist.n_value);
  950. }
  951. }
  952. /*
  953. * Write the Traceback End Module TBT record
  954. */
  955. VMS_TBT_Module_End();
  956. /*
  957. * Write the End Of Module record
  958. */
  959. if (Entry_Point_Symbol == 0)
  960. Write_VMS_EOM_Record(-1,0);
  961. else
  962. Write_VMS_EOM_Record(Text_Psect,
  963. Entry_Point_Symbol->sy_nlist.n_value);
  964. /*
  965. * All done, close the object file
  966. */
  967. Close_VMS_Object_File();
  968. }
  969. /****** VMS OBJECT FILE HACKING ROUTINES *******/
  970. /*
  971. * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
  972. */
  973. static int VMS_Object_File_FD; /* File Descriptor for object file */
  974. static char Object_Record_Buffer[512]; /* Buffer for object file records */
  975. static int Object_Record_Offset; /* Offset to end of data */
  976. static int Current_Object_Record_Type; /* Type of record in above */
  977. /*
  978. * Macros for placing data into the object record buffer
  979. */
  980. #define PUT_LONG(val) *((long *)(Object_Record_Buffer + \
  981. Object_Record_Offset)) = val; \
  982. Object_Record_Offset += sizeof(long)
  983. #define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \
  984. Object_Record_Offset)) = val; \
  985. Object_Record_Offset += sizeof(short)
  986. #define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
  987. #define PUT_COUNTED_STRING(cp) {\
  988. register char *p = cp; \
  989. PUT_CHAR(strlen(p)); \
  990. while(*p) PUT_CHAR(*p++);}
  991. /*
  992. * Macro for determining if a Name has psect attributes attached
  993. * to it.
  994. */
  995. #define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
  996. #define PSECT_ATTRIBUTES_STRING_LENGTH 18
  997. #define HAS_PSECT_ATTRIBUTES(Name) \
  998. (strncmp((Name[0] == '_' ? Name + 1 : Name), \
  999. PSECT_ATTRIBUTES_STRING, \
  1000. PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
  1001. /*
  1002. * Create the VMS object file
  1003. */
  1004. Create_VMS_Object_File()
  1005. {
  1006. #ifdef eunice
  1007. VMS_Object_File_FD = creat(out_file_name, 0777, "var");
  1008. #else eunice
  1009. VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
  1010. #endif eunice
  1011. /*
  1012. * Deal with errors
  1013. */
  1014. if (VMS_Object_File_FD < 0) {
  1015. char Error_Line[256];
  1016. sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
  1017. out_file_name);
  1018. error(Error_Line);
  1019. }
  1020. /*
  1021. * Initialize object file hacking variables
  1022. */
  1023. Object_Record_Offset = 0;
  1024. Current_Object_Record_Type = -1;
  1025. }
  1026. /*
  1027. * Declare a particular type of object file record
  1028. */
  1029. Set_VMS_Object_File_Record(Type)
  1030. int Type;
  1031. {
  1032. /*
  1033. * If the type matches, we are done
  1034. */
  1035. if (Type == Current_Object_Record_Type) return;
  1036. /*
  1037. * Otherwise: flush the buffer
  1038. */
  1039. Flush_VMS_Object_Record_Buffer();
  1040. /*
  1041. * Set the new type
  1042. */
  1043. Current_Object_Record_Type = Type;
  1044. }
  1045. /*
  1046. * Flush the object record buffer to the object file
  1047. */
  1048. Flush_VMS_Object_Record_Buffer()
  1049. {
  1050. int i;
  1051. /*
  1052. * If the buffer is empty, we are done
  1053. */
  1054. if (Object_Record_Offset == 0) return;
  1055. /*
  1056. * Write the data to the file
  1057. */
  1058. i= write(VMS_Object_File_FD,
  1059. Object_Record_Buffer,
  1060. Object_Record_Offset);
  1061. if (i != Object_Record_Offset)
  1062. error("I/O error writing VMS object file");
  1063. /*
  1064. * The buffer is now empty
  1065. */
  1066. Object_Record_Offset = 0;
  1067. }
  1068. /*
  1069. * Close the VMS Object file
  1070. */
  1071. Close_VMS_Object_File()
  1072. {
  1073. close(VMS_Object_File_FD);
  1074. }
  1075. /*
  1076. * Write the MHD (Module Header) records
  1077. */
  1078. Write_VMS_MHD_Records()
  1079. {
  1080. register char *cp,*cp1;
  1081. register int i;
  1082. struct {int Size; char *Ptr;} Descriptor;
  1083. char Module_Name[256];
  1084. char Now[17];
  1085. /*
  1086. * We are writing a module header record
  1087. */
  1088. Set_VMS_Object_File_Record(OBJ$C_HDR);
  1089. /*
  1090. * ***************************
  1091. * *MAIN MODULE HEADER RECORD*
  1092. * ***************************
  1093. *
  1094. * Store record type and header type
  1095. */
  1096. PUT_CHAR(OBJ$C_HDR);
  1097. PUT_CHAR(MHD$C_MHD);
  1098. /*
  1099. * Structure level is 0
  1100. */
  1101. PUT_CHAR(OBJ$C_STRLVL);
  1102. /*
  1103. * Maximum record size is size of the object record buffer
  1104. */
  1105. PUT_SHORT(sizeof(Object_Record_Buffer));
  1106. /*
  1107. * Get module name (the FILENAME part of the object file)
  1108. */
  1109. cp = out_file_name;
  1110. cp1 = Module_Name;
  1111. while(*cp) {
  1112. if ((*cp == ']') || (*cp == '>') ||
  1113. (*cp == ':') || (*cp == '/')) {
  1114. cp1 = Module_Name;
  1115. cp++;
  1116. continue;
  1117. }
  1118. *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
  1119. }
  1120. *cp1 = 0;
  1121. /*
  1122. * Limit it to 31 characters and store in the object record
  1123. */
  1124. while(--cp1 >= Module_Name)
  1125. if (*cp1 == '.') *cp1 = 0;
  1126. if (strlen(Module_Name) > 31) Module_Name[31] = 0;
  1127. PUT_COUNTED_STRING(Module_Name);
  1128. /*
  1129. * Module Version is "V1.0"
  1130. */
  1131. PUT_COUNTED_STRING("V1.0");
  1132. /*
  1133. * Creation time is "now" (17 chars of time string)
  1134. */
  1135. Descriptor.Size = 17;
  1136. Descriptor.Ptr = Now;
  1137. sys$asctim(0,&Descriptor,0,0);
  1138. for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
  1139. /*
  1140. * Patch time is "never" (17 zeros)
  1141. */
  1142. for(i = 0; i < 17; i++) PUT_CHAR(0);
  1143. /*
  1144. * Flush the record
  1145. */
  1146. Flush_VMS_Object_Record_Buffer();
  1147. /*
  1148. * *************************
  1149. * *LANGUAGE PROCESSOR NAME*
  1150. * *************************
  1151. *
  1152. * Store record type and header type
  1153. */
  1154. PUT_CHAR(OBJ$C_HDR);
  1155. PUT_CHAR(MHD$C_LNM);
  1156. /*
  1157. * Store language processor name and version
  1158. * (not a counted string!)
  1159. */
  1160. cp = compiler_version_string;
  1161. if (cp == 0) cp ="GNU AS V1.0";
  1162. while(*cp) PUT_CHAR(*cp++);
  1163. /*
  1164. * Flush the record
  1165. */
  1166. Flush_VMS_Object_Record_Buffer();
  1167. }
  1168. /*
  1169. * Write the EOM (End Of Module) record
  1170. */
  1171. Write_VMS_EOM_Record(Psect, Offset)
  1172. int Psect;
  1173. int Offset;
  1174. {
  1175. /*
  1176. * We are writing an end-of-module record
  1177. */
  1178. Set_VMS_Object_File_Record(OBJ$C_EOM);
  1179. /*
  1180. * Store record Type
  1181. */
  1182. PUT_CHAR(OBJ$C_EOM);
  1183. /*
  1184. * Store the error severity (0)
  1185. */
  1186. PUT_CHAR(0);
  1187. /*
  1188. * Store the entry point, if it exists
  1189. */
  1190. if (Psect >= 0) {
  1191. /*
  1192. * Store the entry point Psect
  1193. */
  1194. PUT_CHAR(Psect);
  1195. /*
  1196. * Store the entry point Psect offset
  1197. */
  1198. PUT_LONG(Offset);
  1199. }
  1200. /*
  1201. * Flush the record
  1202. */
  1203. Flush_VMS_Object_Record_Buffer();
  1204. }
  1205. /*
  1206. * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
  1207. */
  1208. VMS_Case_Hack_Symbol(In,Out)
  1209. register char *In;
  1210. register char *Out;
  1211. {
  1212. register int i;
  1213. int Case_Hack_Bits = 0;
  1214. int Saw_Dollar = 0;
  1215. static char Hex_Table[16] =
  1216. {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  1217. /*
  1218. * Kill any leading "_"
  1219. */
  1220. if (*In == '_') In++;
  1221. /*
  1222. * Is there a Psect Attribute to skip??
  1223. */
  1224. if (HAS_PSECT_ATTRIBUTES(In)) {
  1225. /*
  1226. * Yes: Skip it
  1227. */
  1228. In += PSECT_ATTRIBUTES_STRING_LENGTH;
  1229. while(*In) {
  1230. if ((In[0] == '$') && (In[1] == '$')) {
  1231. In += 2;
  1232. break;
  1233. }
  1234. In++;
  1235. }
  1236. }
  1237. /*
  1238. * Do the case conversion
  1239. */
  1240. i = 23; /* Maximum of 23 chars */
  1241. while(*In && (--i >= 0)) {
  1242. Case_Hack_Bits <<= 1;
  1243. if (*In == '$') Saw_Dollar = 1;
  1244. if (isupper(*In)) {
  1245. *Out++ = *In++;
  1246. Case_Hack_Bits |= 1;
  1247. } else {
  1248. *Out++ = islower(*In) ? toupper(*In++) : *In++;
  1249. }
  1250. }
  1251. /*
  1252. * If we saw a dollar sign, we don't do case hacking
  1253. */
  1254. if (Saw_Dollar) Case_Hack_Bits = 0;
  1255. /*
  1256. * If we have more than 23 characters and everything is lowercase
  1257. * we can insert the full 31 characters
  1258. */
  1259. if (*In) {
  1260. /*
  1261. * We have more than 23 characters
  1262. */
  1263. if (Case_Hack_Bits == 0) {
  1264. /*
  1265. * And so far they are all lower case:
  1266. * Check up to 8 more characters
  1267. * and ensure that they are lowercase
  1268. */
  1269. for(i = 0; (In[i] != 0) && (i < 8); i++)
  1270. if (isupper(In[i]) && !Saw_Dollar) break;
  1271. if ((i >= 8) || (In[i] == 0)) {
  1272. /*
  1273. * They are: Copy up to 31 characters
  1274. * to the output string
  1275. */
  1276. i = 8;
  1277. while((--i >= 0) && (*In))
  1278. *Out++ = islower(*In) ?
  1279. toupper(*In++) :
  1280. *In++;
  1281. }
  1282. }
  1283. }
  1284. /*
  1285. * If there were any uppercase characters in the name we
  1286. * take on the case hacking string
  1287. */
  1288. if (Case_Hack_Bits != 0) {
  1289. *Out++ = '_';
  1290. for(i = 0; i < 6; i++) {
  1291. *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
  1292. Case_Hack_Bits >>= 4;
  1293. }
  1294. *Out++ = 'X';
  1295. }
  1296. /*
  1297. * Done
  1298. */
  1299. *Out = 0;
  1300. }
  1301. /*
  1302. * Scan a symbol name for a psect attribute specification
  1303. */
  1304. VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
  1305. char *Name;
  1306. int *Attribute_Pointer;
  1307. {
  1308. register int i;
  1309. register char *cp;
  1310. int Negate;
  1311. static struct {
  1312. char *Name;
  1313. int Value;
  1314. } Attributes[] = {
  1315. {"PIC", GPS$M_PIC},
  1316. {"LIB", GPS$M_LIB},
  1317. {"OVR", GPS$M_OVR},
  1318. {"REL", GPS$M_REL},
  1319. {"GBL", GPS$M_GBL},
  1320. {"SHR", GPS$M_SHR},
  1321. {"EXE", GPS$M_EXE},
  1322. {"RD", GPS$M_RD},
  1323. {"WRT", GPS$M_WRT},
  1324. {"VEC", GPS$M_VEC},
  1325. {0, 0}};
  1326. /*
  1327. * Kill leading "_"
  1328. */
  1329. if (*Name == '_') Name++;
  1330. /*
  1331. * Check for a PSECT attribute list
  1332. */
  1333. if (!HAS_PSECT_ATTRIBUTES(Name)) return; /* If not, return */
  1334. /*
  1335. * Skip the attribute list indicator
  1336. */
  1337. Name += PSECT_ATTRIBUTES_STRING_LENGTH;
  1338. /*
  1339. * Process the attributes ("_" separated, "$" terminated)
  1340. */
  1341. while(*Name != '$') {
  1342. /*
  1343. * Assume not negating
  1344. */
  1345. Negate = 0;
  1346. /*
  1347. * Check for "NO"
  1348. */
  1349. if ((Name[0] == 'N') && (Name[1] == 'O')) {
  1350. /*
  1351. * We are negating (and skip the NO)
  1352. */
  1353. Negate = 1;
  1354. Name += 2;
  1355. }
  1356. /*
  1357. * Find the token delimiter
  1358. */
  1359. cp = Name;
  1360. while(*cp && (*cp != '_') && (*cp != '$')) cp++;
  1361. /*
  1362. * Look for the token in the attribute list
  1363. */
  1364. for(i = 0; Attributes[i].Name; i++) {
  1365. /*
  1366. * If the strings match, set/clear the attr.
  1367. */
  1368. if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
  1369. /*
  1370. * Set or clear
  1371. */
  1372. if (Negate)
  1373. *Attribute_Pointer &=
  1374. ~Attributes[i].Value;
  1375. else
  1376. *Attribute_Pointer |=
  1377. Attributes[i].Value;
  1378. /*
  1379. * Done
  1380. */
  1381. break;
  1382. }
  1383. }
  1384. /*
  1385. * Now skip the attribute
  1386. */
  1387. Name = cp;
  1388. if (*Name == '_') Name++;
  1389. }
  1390. /*
  1391. * Done
  1392. */
  1393. return;
  1394. }
  1395. /*
  1396. * Define a psect
  1397. */
  1398. VMS_Psect_Spec(Name, Size, Type)
  1399. char *Name;
  1400. int Size;
  1401. char *Type;
  1402. {
  1403. char Local[32];
  1404. int Psect_Attributes;
  1405. /*
  1406. * We are writing a GSD record
  1407. */
  1408. Set_VMS_Object_File_Record(OBJ$C_GSD);
  1409. /*
  1410. * If the buffer is empty we must insert the GSD record type
  1411. */
  1412. if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1413. /*
  1414. * We are writing a PSECT definition subrecord
  1415. */
  1416. PUT_CHAR(GSD$C_PSC);
  1417. /*
  1418. * Psects are always LONGWORD aligned
  1419. */
  1420. PUT_CHAR(2);
  1421. /*
  1422. * Generate the appropriate PSECT flags given the PSECT type
  1423. */
  1424. if (strcmp(Type,"COMMON") == 0) {
  1425. /*
  1426. * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
  1427. */
  1428. Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
  1429. GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
  1430. } else {
  1431. if (strcmp(Type,"DATA") == 0) {
  1432. /*
  1433. * The Data psects are PIC,REL,RD,WRT
  1434. */
  1435. Psect_Attributes =
  1436. (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
  1437. } else {
  1438. if (strcmp(Type,"TEXT") == 0) {
  1439. /*
  1440. * The Text psects are PIC,REL,SHR,EXE,RD
  1441. */
  1442. Psect_Attributes =
  1443. (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
  1444. GPS$M_EXE|GPS$M_RD);
  1445. } else {
  1446. /*
  1447. * Error: Unknown psect type
  1448. */
  1449. error("Unknown VMS psect type");
  1450. }
  1451. }
  1452. }
  1453. /*
  1454. * Modify the psect attributes according to any attribute string
  1455. */
  1456. if (HAS_PSECT_ATTRIBUTES(Name))
  1457. VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
  1458. /*
  1459. * Specify the psect attributes
  1460. */
  1461. PUT_SHORT(Psect_Attributes);
  1462. /*
  1463. * Specify the allocation
  1464. */
  1465. PUT_LONG(Size);
  1466. /*
  1467. * Finally, the psect name
  1468. */
  1469. VMS_Case_Hack_Symbol(Name,Local);
  1470. PUT_COUNTED_STRING(Local);
  1471. /*
  1472. * Flush the buffer if it is more than 75% full
  1473. */
  1474. if (Object_Record_Offset >
  1475. (sizeof(Object_Record_Buffer)*3/4))
  1476. Flush_VMS_Object_Record_Buffer();
  1477. }
  1478. /*
  1479. * Define a global symbol
  1480. */
  1481. VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
  1482. char *Name;
  1483. int Psect_Number;
  1484. int Psect_Offset;
  1485. {
  1486. char Local[32];
  1487. /*
  1488. * We are writing a GSD record
  1489. */
  1490. Set_VMS_Object_File_Record(OBJ$C_GSD);
  1491. /*
  1492. * If the buffer is empty we must insert the GSD record type
  1493. */
  1494. if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1495. /*
  1496. * We are writing a Global symbol definition subrecord
  1497. */
  1498. if (Psect_Number <= 255) {
  1499. PUT_CHAR(GSD$C_SYM);
  1500. } else {
  1501. PUT_CHAR(GSD$C_SYMW);
  1502. }
  1503. /*
  1504. * Data type is undefined
  1505. */
  1506. PUT_CHAR(0);
  1507. /*
  1508. * Switch on Definition/Reference
  1509. */
  1510. if (Defined) {
  1511. /*
  1512. * Definition:
  1513. * Flags = "RELOCATABLE" and "DEFINED"
  1514. */
  1515. PUT_SHORT(GSY$M_DEF|GSY$M_REL);
  1516. /*
  1517. * Psect Number
  1518. */
  1519. if (Psect_Number <= 255) {
  1520. PUT_CHAR(Psect_Number);
  1521. } else {
  1522. PUT_SHORT(Psect_Number);
  1523. }
  1524. /*
  1525. * Offset
  1526. */
  1527. PUT_LONG(Psect_Offset);
  1528. } else {
  1529. /*
  1530. * Reference:
  1531. * Flags = "RELOCATABLE"
  1532. */
  1533. PUT_SHORT(GSY$M_REL);
  1534. }
  1535. /*
  1536. * Finally, the global symbol name
  1537. */
  1538. VMS_Case_Hack_Symbol(Name,Local);
  1539. PUT_COUNTED_STRING(Local);
  1540. /*
  1541. * Flush the buffer if it is more than 75% full
  1542. */
  1543. if (Object_Record_Offset >
  1544. (sizeof(Object_Record_Buffer)*3/4))
  1545. Flush_VMS_Object_Record_Buffer();
  1546. }
  1547. /*
  1548. * Define a procedure entry pt/mask
  1549. */
  1550. VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
  1551. char *Name;
  1552. int Psect_Number;
  1553. int Psect_Offset;
  1554. int Entry_Mask;
  1555. {
  1556. char Local[32];
  1557. /*
  1558. * We are writing a GSD record
  1559. */
  1560. Set_VMS_Object_File_Record(OBJ$C_GSD);
  1561. /*
  1562. * If the buffer is empty we must insert the GSD record type
  1563. */
  1564. if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1565. /*
  1566. * We are writing a Procedure Entry Pt/Mask subrecord
  1567. */
  1568. if (Psect_Number <= 255) {
  1569. PUT_CHAR(GSD$C_EPM);
  1570. } else {
  1571. PUT_CHAR(GSD$C_EPMW);
  1572. }
  1573. /*
  1574. * Data type is undefined
  1575. */
  1576. PUT_CHAR(0);
  1577. /*
  1578. * Flags = "RELOCATABLE" and "DEFINED"
  1579. */
  1580. PUT_SHORT(GSY$M_DEF|GSY$M_REL);
  1581. /*
  1582. * Psect Number
  1583. */
  1584. if (Psect_Number <= 255) {
  1585. PUT_CHAR(Psect_Number);
  1586. } else {
  1587. PUT_SHORT(Psect_Number);
  1588. }
  1589. /*
  1590. * Offset
  1591. */
  1592. PUT_LONG(Psect_Offset);
  1593. /*
  1594. * Entry mask
  1595. */
  1596. PUT_SHORT(Entry_Mask);
  1597. /*
  1598. * Finally, the global symbol name
  1599. */
  1600. VMS_Case_Hack_Symbol(Name,Local);
  1601. PUT_COUNTED_STRING(Local);
  1602. /*
  1603. * Flush the buffer if it is more than 75% full
  1604. */
  1605. if (Object_Record_Offset >
  1606. (sizeof(Object_Record_Buffer)*3/4))
  1607. Flush_VMS_Object_Record_Buffer();
  1608. }
  1609. /*
  1610. * Set the current location counter to a particular Psect and Offset
  1611. */
  1612. VMS_Set_Psect(Psect_Index, Offset, Record_Type)
  1613. int Psect_Index;
  1614. int Offset;
  1615. int Record_Type;
  1616. {
  1617. /*
  1618. * We are writing a "Record_Type" record
  1619. */
  1620. Set_VMS_Object_File_Record(Record_Type);
  1621. /*
  1622. * If the buffer is empty we must insert the record type
  1623. */
  1624. if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1625. /*
  1626. * Stack the Psect base + Longword Offset
  1627. */
  1628. if (Psect_Index < 255) {
  1629. PUT_CHAR(TIR$C_STA_PL);
  1630. PUT_CHAR(Psect_Index);
  1631. } else {
  1632. PUT_CHAR(TIR$C_STA_WPL);
  1633. PUT_SHORT(Psect_Index);
  1634. }
  1635. PUT_LONG(Offset);
  1636. /*
  1637. * Set relocation base
  1638. */
  1639. PUT_CHAR(TIR$C_CTL_SETRB);
  1640. /*
  1641. * Flush the buffer if it is more than 75% full
  1642. */
  1643. if (Object_Record_Offset >
  1644. (sizeof(Object_Record_Buffer)*3/4))
  1645. Flush_VMS_Object_Record_Buffer();
  1646. }
  1647. /*
  1648. * Store immediate data in current Psect
  1649. */
  1650. VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
  1651. register char *Pointer;
  1652. int Size;
  1653. int Record_Type;
  1654. {
  1655. register int i;
  1656. /*
  1657. * We are writing a "Record_Type" record
  1658. */
  1659. Set_VMS_Object_File_Record(Record_Type);
  1660. /*
  1661. * We can only store 128 bytes at a time
  1662. */
  1663. while(Size > 0) {
  1664. /*
  1665. * Store a maximum of 128 bytes
  1666. */
  1667. i = (Size > 128) ? 128 : Size;
  1668. Size -= i;
  1669. /*
  1670. * If we cannot accommodate this record, flush the
  1671. * buffer.
  1672. */
  1673. if ((Object_Record_Offset + i + 1) >=
  1674. sizeof(Object_Record_Buffer))
  1675. Flush_VMS_Object_Record_Buffer();
  1676. /*
  1677. * If the buffer is empty we must insert record type
  1678. */
  1679. if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1680. /*
  1681. * Store the count
  1682. */
  1683. PUT_CHAR(-i & 0xff);
  1684. /*
  1685. * Store the data
  1686. */
  1687. while(--i >= 0) PUT_CHAR(*Pointer++);
  1688. /*
  1689. * Flush the buffer if it is more than 75% full
  1690. */
  1691. if (Object_Record_Offset >
  1692. (sizeof(Object_Record_Buffer)*3/4))
  1693. Flush_VMS_Object_Record_Buffer();
  1694. }
  1695. }
  1696. /*
  1697. * Store repeated immediate data in current Psect
  1698. */
  1699. VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
  1700. int Repeat_Count;
  1701. register char *Pointer;
  1702. int Size;
  1703. int Record_Type;
  1704. {
  1705. /*
  1706. * Ignore zero bytes/words/longwords
  1707. */
  1708. if ((Size == sizeof(char)) && (*Pointer == 0)) return;
  1709. if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
  1710. if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
  1711. /*
  1712. * If the data is too big for a TIR$C_STO_RIVB sub-record
  1713. * then we do it manually
  1714. */
  1715. if (Size > 255) {
  1716. while(--Repeat_Count >= 0)
  1717. VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
  1718. return;
  1719. }
  1720. /*
  1721. * We are writing a "Record_Type" record
  1722. */
  1723. Set_VMS_Object_File_Record(Record_Type);
  1724. /*
  1725. * If the buffer is empty we must insert record type
  1726. */
  1727. if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1728. /*
  1729. * Stack the repeat count
  1730. */
  1731. PUT_CHAR(TIR$C_STA_LW);
  1732. PUT_LONG(Repeat_Count);
  1733. /*
  1734. * And now the command and its data
  1735. */
  1736. PUT_CHAR(TIR$C_STO_RIVB);
  1737. PUT_CHAR(Size);
  1738. while(--Size >= 0) PUT_CHAR(*Pointer++);
  1739. /*
  1740. * Flush the buffer if it is more than 75% full
  1741. */
  1742. if (Object_Record_Offset >
  1743. (sizeof(Object_Record_Buffer)*3/4))
  1744. Flush_VMS_Object_Record_Buffer();
  1745. }
  1746. /*
  1747. * Store a Position Independent Reference
  1748. */
  1749. VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
  1750. Psect, Psect_Offset, Record_Type)
  1751. struct symbol *Symbol;
  1752. int Offset;
  1753. int PC_Relative;
  1754. int Psect;
  1755. int Psect_Offset;
  1756. int Record_Type;
  1757. {
  1758. register struct VMS_Symbol *vsp =
  1759. (struct VMS_Symbol *)(Symbol->sy_number);
  1760. char Local[32];
  1761. /*
  1762. * We are writing a "Record_Type" record
  1763. */
  1764. Set_VMS_Object_File_Record(Record_Type);
  1765. /*
  1766. * If the buffer is empty we must insert record type
  1767. */
  1768. if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1769. /*
  1770. * Set to the appropriate offset in the Psect
  1771. */
  1772. if (PC_Relative) {
  1773. /*
  1774. * For a Code reference we need to fix the operand
  1775. * specifier as well (so back up 1 byte)
  1776. */
  1777. VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
  1778. } else {
  1779. /*
  1780. * For a Data reference we just store HERE
  1781. */
  1782. VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
  1783. }
  1784. /*
  1785. * Make sure we are still generating a "Record Type" record
  1786. */
  1787. if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1788. /*
  1789. * Dispatch on symbol type (so we can stack its value)
  1790. */
  1791. switch(Symbol->sy_nlist.n_type) {
  1792. /*
  1793. * Global symbol
  1794. */
  1795. #ifdef NOT_VAX_11_C_COMPATIBLE
  1796. case N_UNDF | N_EXT:
  1797. case N_DATA | N_EXT:
  1798. #endif NOT_VAX_11_C_COMPATIBLE
  1799. case N_UNDF:
  1800. case N_TEXT | N_EXT:
  1801. /*
  1802. * Get the symbol name (case hacked)
  1803. */
  1804. VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
  1805. /*
  1806. * Stack the global symbol value
  1807. */
  1808. PUT_CHAR(TIR$C_STA_GBL);
  1809. PUT_COUNTED_STRING(Local);
  1810. if (Offset) {
  1811. /*
  1812. * Stack the longword offset
  1813. */
  1814. PUT_CHAR(TIR$C_STA_LW);
  1815. PUT_LONG(Offset);
  1816. /*
  1817. * Add the two, leaving the result on the stack
  1818. */
  1819. PUT_CHAR(TIR$C_OPR_ADD);
  1820. }
  1821. break;
  1822. /*
  1823. * Uninitialized local data
  1824. */
  1825. case N_BSS:
  1826. /*
  1827. * Stack the Psect (+offset)
  1828. */
  1829. if (vsp->Psect_Index < 255) {
  1830. PUT_CHAR(TIR$C_STA_PL);
  1831. PUT_CHAR(vsp->Psect_Index);
  1832. } else {
  1833. PUT_CHAR(TIR$C_STA_WPL);
  1834. PUT_SHORT(vsp->Psect_Index);
  1835. }
  1836. PUT_LONG(vsp->Psect_Offset + Offset);
  1837. break;
  1838. /*
  1839. * Local text
  1840. */
  1841. case N_TEXT:
  1842. /*
  1843. * Stack the Psect (+offset)
  1844. */
  1845. if (vsp->Psect_Index < 255) {
  1846. PUT_CHAR(TIR$C_STA_PL);
  1847. PUT_CHAR(vsp->Psect_Index);
  1848. } else {
  1849. PUT_CHAR(TIR$C_STA_WPL);
  1850. PUT_SHORT(vsp->Psect_Index);
  1851. }
  1852. PUT_LONG(Symbol->sy_nlist.n_value);
  1853. break;
  1854. /*
  1855. * Initialized local or global data
  1856. */
  1857. case N_DATA:
  1858. #ifndef NOT_VAX_11_C_COMPATIBLE
  1859. case N_UNDF | N_EXT:
  1860. case N_DATA | N_EXT:
  1861. #endif NOT_VAX_11_C_COMPATIBLE
  1862. /*
  1863. * Stack the Psect (+offset)
  1864. */
  1865. if (vsp->Psect_Index < 255) {
  1866. PUT_CHAR(TIR$C_STA_PL);
  1867. PUT_CHAR(vsp->Psect_Index);
  1868. } else {
  1869. PUT_CHAR(TIR$C_STA_WPL);
  1870. PUT_SHORT(vsp->Psect_Index);
  1871. }
  1872. PUT_LONG(vsp->Psect_Offset + Offset);
  1873. break;
  1874. }
  1875. /*
  1876. * Store either a code or data reference
  1877. */
  1878. PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
  1879. /*
  1880. * Flush the buffer if it is more than 75% full
  1881. */
  1882. if (Object_Record_Offset >
  1883. (sizeof(Object_Record_Buffer)*3/4))
  1884. Flush_VMS_Object_Record_Buffer();
  1885. }
  1886. /*
  1887. * Check in the text area for an indirect pc-relative reference
  1888. * and fix it up with addressing mode 0xff [PC indirect]
  1889. *
  1890. * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
  1891. * PIC CODE GENERATING FIXUP ROUTINE.
  1892. */
  1893. VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
  1894. int Text_Psect;
  1895. int Offset;
  1896. register fragS *fragP;
  1897. struct frag *text_frag_root;
  1898. {
  1899. /*
  1900. * The addressing mode byte is 1 byte before the address
  1901. */
  1902. Offset--;
  1903. /*
  1904. * Is it in THIS frag??
  1905. */
  1906. if ((Offset < fragP->fr_address) ||
  1907. (Offset >= (fragP->fr_address + fragP->fr_fix))) {
  1908. /*
  1909. * We need to search for the fragment containing this
  1910. * Offset
  1911. */
  1912. for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  1913. if ((Offset >= fragP->fr_address) &&
  1914. (Offset < (fragP->fr_address + fragP->fr_fix)))
  1915. break;
  1916. }
  1917. /*
  1918. * If we couldn't find the frag, things are BAD!!
  1919. */
  1920. if (fragP == 0)
  1921. error("Couldn't find fixup fragment when checking for indirect reference");
  1922. }
  1923. /*
  1924. * Check for indirect PC relative addressing mode
  1925. */
  1926. if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
  1927. static char Address_Mode = 0xff;
  1928. /*
  1929. * Yes: Store the indirect mode back into the image
  1930. * to fix up the damage done by STO_PICR
  1931. */
  1932. VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
  1933. VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
  1934. }
  1935. }
  1936. /*
  1937. * Write the Traceback Module Begin record
  1938. */
  1939. VMS_TBT_Module_Begin()
  1940. {
  1941. register char *cp,*cp1;
  1942. int Size;
  1943. char Module_Name[256];
  1944. char Local[256];
  1945. /*
  1946. * Get module name (the FILENAME part of the object file)
  1947. */
  1948. cp = out_file_name;
  1949. cp1 = Module_Name;
  1950. while(*cp) {
  1951. if ((*cp == ']') || (*cp == '>') ||
  1952. (*cp == ':') || (*cp == '/')) {
  1953. cp1 = Module_Name;
  1954. cp++;
  1955. continue;
  1956. }
  1957. *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
  1958. }
  1959. *cp1 = 0;
  1960. /*
  1961. * Limit it to 31 characters
  1962. */
  1963. while(--cp1 >= Module_Name)
  1964. if (*cp1 == '.') *cp1 = 0;
  1965. if (strlen(Module_Name) > 31) Module_Name[31] = 0;
  1966. /*
  1967. * Arrange to store the data locally (leave room for size byte)
  1968. */
  1969. cp = Local+1;
  1970. /*
  1971. * Begin module
  1972. */
  1973. *cp++ = DST$C_MODBEG;
  1974. /*
  1975. * Unused
  1976. */
  1977. *cp++ = 0;
  1978. /*
  1979. * Language type == "C"
  1980. */
  1981. *(long *)cp = DST$C_C;
  1982. cp += sizeof(long);
  1983. /*
  1984. * Store the module name
  1985. */
  1986. *cp++ = strlen(Module_Name);
  1987. cp1 = Module_Name;
  1988. while(*cp1) *cp++ = *cp1++;
  1989. /*
  1990. * Now we can store the record size
  1991. */
  1992. Size = (cp - Local);
  1993. Local[0] = Size-1;
  1994. /*
  1995. * Put it into the object record
  1996. */
  1997. VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
  1998. }
  1999. /*
  2000. * Write the Traceback Module End record
  2001. */
  2002. VMS_TBT_Module_End()
  2003. {
  2004. char Local[2];
  2005. /*
  2006. * End module
  2007. */
  2008. Local[0] = 1;
  2009. Local[1] = DST$C_MODEND;
  2010. /*
  2011. * Put it into the object record
  2012. */
  2013. VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
  2014. }
  2015. /*
  2016. * Write the Traceback Routine Begin record
  2017. */
  2018. VMS_TBT_Routine_Begin(symbolP, Psect)
  2019. struct symbol *symbolP;
  2020. int Psect;
  2021. {
  2022. register char *cp,*cp1;
  2023. char *Name;
  2024. int Offset;
  2025. int Size;
  2026. char Local[512];
  2027. /*
  2028. * Strip the leading "_" from the name
  2029. */
  2030. Name = symbolP->sy_nlist.n_un.n_name;
  2031. if (*Name == '_') Name++;
  2032. /*
  2033. * Get the text psect offset
  2034. */
  2035. Offset = symbolP->sy_nlist.n_value;
  2036. /*
  2037. * Calculate the record size
  2038. */
  2039. Size = 1+1+4+1+strlen(Name);
  2040. /*
  2041. * Record Size
  2042. */
  2043. Local[0] = Size;
  2044. /*
  2045. * Begin Routine
  2046. */
  2047. Local[1] = DST$C_RTNBEG;
  2048. /*
  2049. * Uses CallS/CallG
  2050. */
  2051. Local[2] = 0;
  2052. /*
  2053. * Store the data so far
  2054. */
  2055. VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
  2056. /*
  2057. * Make sure we are still generating a OBJ$C_TBT record
  2058. */
  2059. if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
  2060. /*
  2061. * Now get the symbol address
  2062. */
  2063. PUT_CHAR(TIR$C_STA_WPL);
  2064. PUT_SHORT(Psect);
  2065. PUT_LONG(Offset);
  2066. /*
  2067. * Store the data reference
  2068. */
  2069. PUT_CHAR(TIR$C_STO_PIDR);
  2070. /*
  2071. * Store the counted string as data
  2072. */
  2073. cp = Local;
  2074. cp1 = Name;
  2075. Size = strlen(cp1) + 1;
  2076. *cp++ = Size - 1;
  2077. while(*cp1) *cp++ = *cp1++;
  2078. VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
  2079. }
  2080. /*
  2081. * Write the Traceback Routine End record
  2082. */
  2083. VMS_TBT_Routine_End(Size)
  2084. {
  2085. char Local[16];
  2086. /*
  2087. * Record Size
  2088. */
  2089. Local[0] = 6;
  2090. /*
  2091. * End of Routine
  2092. */
  2093. Local[1] = DST$C_RTNEND;
  2094. /*
  2095. * Unused
  2096. */
  2097. Local[2] = 0;
  2098. /*
  2099. * Size of routine
  2100. */
  2101. *((long *)(Local+3)) = Size;
  2102. /*
  2103. * Store the record
  2104. */
  2105. VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
  2106. }
  2107. /*
  2108. * Write a Line number / PC correlation record
  2109. */
  2110. VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
  2111. int Line_Number;
  2112. int Offset;
  2113. int Psect;
  2114. int Do_Delta;
  2115. {
  2116. register char *cp;
  2117. char Local[64];
  2118. /*
  2119. * If not delta, set our PC/Line number correlation
  2120. */
  2121. if (Do_Delta == 0) {
  2122. /*
  2123. * Size
  2124. */
  2125. Local[0] = 1+1+2+1+4;
  2126. /*
  2127. * Line Number/PC correlation
  2128. */
  2129. Local[1] = DST$C_LINE_NUM;
  2130. /*
  2131. * Set Line number
  2132. */
  2133. Local[2] = DST$C_SET_LINE_NUM;
  2134. *((unsigned short *)(Local+3)) = Line_Number-1;
  2135. /*
  2136. * Set PC
  2137. */
  2138. Local[5] = DST$C_SET_ABS_PC;
  2139. VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
  2140. /*
  2141. * Make sure we are still generating a OBJ$C_TBT record
  2142. */
  2143. if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
  2144. if (Psect < 255) {
  2145. PUT_CHAR(TIR$C_STA_PL);
  2146. PUT_CHAR(Psect);
  2147. } else {
  2148. PUT_CHAR(TIR$C_STA_WPL);
  2149. PUT_SHORT(Psect);
  2150. }
  2151. PUT_LONG(Offset);
  2152. PUT_CHAR(TIR$C_STO_PIDR);
  2153. /*
  2154. * Do a PC offset of 0 to register the line number
  2155. */
  2156. Local[0] = 2;
  2157. Local[1] = DST$C_LINE_NUM;
  2158. Local[2] = 0; /* Increment PC by 0 and register line # */
  2159. VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
  2160. } else {
  2161. /*
  2162. * If Delta is negative, terminate the line numbers
  2163. */
  2164. if (Do_Delta < 0) {
  2165. Local[0] = 1+1+4;
  2166. Local[1] = DST$C_LINE_NUM;
  2167. Local[2] = DST$C_TERM_L;
  2168. *((long *)(Local+3)) = Offset;
  2169. VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
  2170. /*
  2171. * Done
  2172. */
  2173. return;
  2174. }
  2175. /*
  2176. * Do a PC/Line delta
  2177. */
  2178. cp = Local+1;
  2179. *cp++ = DST$C_LINE_NUM;
  2180. if (Line_Number > 1) {
  2181. /*
  2182. * We need to increment the line number
  2183. */
  2184. if (Line_Number-1 <= 255) {
  2185. *cp++ = DST$C_INCR_LINUM;
  2186. *cp++ = Line_Number-1;
  2187. } else {
  2188. *cp++ = DST$C_INCR_LINUM_W;
  2189. *(short *)cp = Line_Number-1;
  2190. cp += sizeof(short);
  2191. }
  2192. }
  2193. /*
  2194. * Increment the PC
  2195. */
  2196. if (Offset <= 128) {
  2197. *cp++ = -Offset;
  2198. } else {
  2199. if (Offset < 0x10000) {
  2200. *cp++ = DST$C_DELTA_PC_W;
  2201. *(short *)cp = Offset;
  2202. cp += sizeof(short);
  2203. } else {
  2204. *cp++ = DST$C_DELTA_PC_L;
  2205. *(long *)cp = Offset;
  2206. cp += sizeof(long);
  2207. }
  2208. }
  2209. Local[0] = cp - (Local+1);
  2210. VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
  2211. }
  2212. }
  2213. /*
  2214. * Describe a source file to the debugger
  2215. */
  2216. VMS_TBT_Source_File(Filename, ID_Number)
  2217. char *Filename;
  2218. int ID_Number;
  2219. {
  2220. register char *cp,*cp1;
  2221. int Status,i;
  2222. char Local[512];
  2223. static struct FAB Fab;
  2224. static struct NAM Nam;
  2225. static struct XABDAT Date_Xab;
  2226. static struct XABFHC File_Header_Xab;
  2227. char Es_String[255],Rs_String[255];
  2228. /*
  2229. * Setup the Fab
  2230. */
  2231. Fab.fab$b_bid = FAB$C_BID;
  2232. Fab.fab$b_bln = sizeof(Fab);
  2233. Fab.fab$l_nam = (&Nam);
  2234. Fab.fab$l_xab = (struct XAB *)&Date_Xab;
  2235. /*
  2236. * Setup the Nam block so we can find out the FULL name
  2237. * of the source file.
  2238. */
  2239. Nam.nam$b_bid = NAM$C_BID;
  2240. Nam.nam$b_bln = sizeof(Nam);
  2241. Nam.nam$l_rsa = Rs_String;
  2242. Nam.nam$b_rss = sizeof(Rs_String);
  2243. Nam.nam$l_esa = Es_String;
  2244. Nam.nam$b_ess = sizeof(Es_String);
  2245. /*
  2246. * Setup the Date and File Header Xabs
  2247. */
  2248. ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT;
  2249. ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab);
  2250. ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab;
  2251. ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC;
  2252. ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab);
  2253. /*
  2254. * Get the file information
  2255. */
  2256. Fab.fab$l_fna = Filename;
  2257. Fab.fab$b_fns = strlen(Filename);
  2258. Status = sys$open(&Fab);
  2259. if (!(Status & 1)) {
  2260. printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
  2261. Filename, Status);
  2262. return(0);
  2263. }
  2264. sys$close(&Fab);
  2265. /*
  2266. * Calculate the size of the resultant string
  2267. */
  2268. i = Nam.nam$b_rsl;
  2269. /*
  2270. * Size of record
  2271. */
  2272. Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1+1+2+1+4;
  2273. /*
  2274. * Source declaration
  2275. */
  2276. Local[1] = DST$C_SOURCE;
  2277. /*
  2278. * Make formfeeds count as source records
  2279. */
  2280. Local[2] = DST$C_SRC_FORMFEED;
  2281. /*
  2282. * Declare source file
  2283. */
  2284. Local[3] = DST$C_SRC_DECLFILE;
  2285. Local[4] = 1+2+8+4+2+1+1+i+1;
  2286. cp = Local+5;
  2287. /*
  2288. * Flags
  2289. */
  2290. *cp++ = 0;
  2291. /*
  2292. * File ID
  2293. */
  2294. *(short *)cp = ID_Number;
  2295. cp += sizeof(short);
  2296. /*
  2297. * Creation Date
  2298. */
  2299. *(long *)cp = Date_Xab.xab$q_cdt[0];
  2300. cp += sizeof(long);
  2301. *(long *)cp = Date_Xab.xab$q_cdt[1];
  2302. cp += sizeof(long);
  2303. /*
  2304. * End of file block
  2305. */
  2306. *(long *)cp = File_Header_Xab.xab$l_ebk;
  2307. cp += sizeof(long);
  2308. /*
  2309. * First free byte
  2310. */
  2311. *(short *)cp = File_Header_Xab.xab$w_ffb;
  2312. cp += sizeof(short);
  2313. /*
  2314. * Record format
  2315. */
  2316. *cp++ = File_Header_Xab.xab$b_rfo;
  2317. /*
  2318. * Filename
  2319. */
  2320. *cp++ = i;
  2321. cp1 = Rs_String;
  2322. while(--i >= 0) *cp++ = *cp1++;
  2323. /*
  2324. * Library module name (none)
  2325. */
  2326. *cp++ = 0;
  2327. /*
  2328. * Set Source File
  2329. */
  2330. *cp++ = DST$C_SRC_SETFILE;
  2331. /*
  2332. * File ID Number
  2333. */
  2334. *(short *)cp = ID_Number;
  2335. cp += sizeof(short);
  2336. /*
  2337. * Set record number
  2338. */
  2339. *cp++ = DST$C_SRC_SETREC_L;
  2340. *(long *)cp = 1;
  2341. cp += sizeof(long);
  2342. /*
  2343. * Done
  2344. */
  2345. VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
  2346. }
  2347. /*
  2348. * Give the number of source lines to the debugger
  2349. */
  2350. VMS_TBT_Source_Lines(Number_Of_Lines)
  2351. int Number_Of_Lines;
  2352. {
  2353. char Local[8];
  2354. /*
  2355. * Size of record
  2356. */
  2357. Local[0] = 1+1+2;
  2358. /*
  2359. * Source declaration
  2360. */
  2361. Local[1] = DST$C_SOURCE;
  2362. /*
  2363. * Define lines
  2364. */
  2365. Local[2] = DST$C_SRC_DEFLINES_W;
  2366. *(short *)(Local+3) = Number_Of_Lines;
  2367. /*
  2368. * Done
  2369. */
  2370. VMS_Store_Immediate_Data(Local, 5, OBJ$C_TBT);
  2371. }
  2372. /*
  2373. * Given the pointer to a symbol we calculate how big the data at the
  2374. * symbol is. We do this by looking for the next symbol (local or
  2375. * global) which will indicate the start of another datum.
  2376. */
  2377. int VMS_Initialized_Data_Size(sp, End_Of_Data)
  2378. register struct symbol *sp;
  2379. int End_Of_Data;
  2380. {
  2381. register struct symbol *sp1,*Next_Symbol;
  2382. /*
  2383. * Find the next symbol
  2384. * it delimits this datum
  2385. */
  2386. Next_Symbol = 0;
  2387. for (sp1 = symbol_rootP; sp1; sp1 = sp1->sy_next) {
  2388. /*
  2389. * The data type must match
  2390. */
  2391. if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
  2392. /*
  2393. * The symbol must be AFTER this symbol
  2394. */
  2395. if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
  2396. /*
  2397. * We ignore THIS symbol
  2398. */
  2399. if (sp1 == sp) continue;
  2400. /*
  2401. * If there is already a candidate selected for the
  2402. * next symbol, see if we are a better candidate
  2403. */
  2404. if (Next_Symbol) {
  2405. /*
  2406. * We are a better candidate if we are "closer"
  2407. * to the symbol
  2408. */
  2409. if (sp1->sy_nlist.n_value >
  2410. Next_Symbol->sy_nlist.n_value)
  2411. continue;
  2412. /*
  2413. * Win: Make this the candidate
  2414. */
  2415. Next_Symbol = sp1;
  2416. } else {
  2417. /*
  2418. * This is the 1st candidate
  2419. */
  2420. Next_Symbol = sp1;
  2421. }
  2422. }
  2423. /*
  2424. * Calculate its size
  2425. */
  2426. return(Next_Symbol ?
  2427. (Next_Symbol->sy_nlist.n_value -
  2428. sp->sy_nlist.n_value) :
  2429. (End_Of_Data - sp->sy_nlist.n_value));
  2430. }
  2431. /*
  2432. * This is a hacked _doprnt() for VAX-11 "C". It understands that
  2433. * it is ONLY called by as_fatal(Format, Args) with a pointer to the
  2434. * "Args" argument. From this we can make it all work right!
  2435. */
  2436. #ifndef eunice
  2437. _doprnt(Format, a, f)
  2438. char *Format;
  2439. FILE *f;
  2440. char **a;
  2441. {
  2442. int Nargs = ((int *)a)[-2]; /* This understands as_fatal() */
  2443. switch(Nargs) {
  2444. default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
  2445. case 1: fprintf(f,Format); break;
  2446. case 2: fprintf(f,Format,a[0]); break;
  2447. case 3: fprintf(f,Format,a[0],a[1]); break;
  2448. case 4: fprintf(f,Format,a[0],a[1],a[2]); break;
  2449. case 5: fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
  2450. case 6: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
  2451. case 7: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
  2452. case 8: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
  2453. case 9: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
  2454. case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
  2455. }
  2456. }
  2457. #endif /* eunice */
  2458. #endif /* VMS */