Operating System - OpenVMS
1827892 Members
1859 Online
109969 Solutions
New Discussion

Re: ANALYZE/IMAGE callable interface?

 
SOLVED
Go to solution
Kay Dolle
Advisor

ANALYZE/IMAGE callable interface?

Hi, we are used to link our images with an ID over the optionfile. On DCL we can determine that with ANALYZE/IMAGE/SELECT=IDENTIFICATION=IMAGE, but is there an LIB$ or an SYS$ to retrieve that information in a program?
Background: we are porting from ALPHA to I64 and out old function reads the image file at an fixed position. The position has changed on I64 and we would like to do it better now...
24 REPLIES 24
Wim Van den Wyngaert
Honored Contributor
Solution

Re: ANALYZE/IMAGE callable interface?

Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

Great, Wim!
Thank you Steve Hoffman!
Kay
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

Kay,

Is that really working for you?
Seems like Alpha code to me.
You need some ELF functions like elf_getindent.

If you link Hoff's example with /sysexe then the critical function IMG$DECODE_IHD is resolved but does work as coded.


Is this for the purpose of obtaining the image ident for the current image?

For ALPHA ... and if you are willing to link /sysexe without actually calling system stuff, or willing to hardcode a defintion of MMG$IMGHDRBUF to be 7FFCF800 you can use the code I wrote below. I wrote the example for intended cobol usage in a shareable library. Sample below.

Regards,
Hein van den Heuvel

$
$ type GET_IDENT.C
/*
** Compile with: sys$library:sys$lib_c.tlb/lib
** Link with /sysexe
*/
#include
#include
#include
#include

#define MOVE_FIELD(f) \
p = &eihi->eihi$t_ ## f ## [0]; \
l = *p++; \
ident-> ## f ## _length = l; \
p = memcpy ( &ident-> ## f ## , p, l ); \
e = p + sizeof ident-> ## f ; \
p += l; \
while (p < e) *p++ = ' ';\
*p = 0;

struct image_identification {
unsigned int imgnam_length;
unsigned int imgid_length;
unsigned int linkid_length;
unsigned int imgbid_length;

unsigned __int64 linktime; /*DATE TIME THIS IMAGE WAS LINKED */
char imgnam[40]; /*IMAGE NAME STRING */
char imgid[16]; /*IMAGE IDENT STRING */
char linkid[16]; /*LINKER IDENT STRING */
char imgbid[16]; /*IMAGE BUILD IDENT STRING */
char linktime_text[24];
};

unsigned int sys$asctim();

globalref EIHD *MMG$IMGHDRBUF;

unsigned int get_image_name_and_ident (struct image_identification *ident)
{
struct {int len; char *addr;} time_desc;
EIHD *eihd;
EIHI *eihi;
unsigned int l, s;
char *p, *e;
eihd = MMG$IMGHDRBUF;
eihi = (EIHI *)((char *) eihd + eihd->eihd$l_imgidoff);


ident->linktime = eihi->eihi$q_linktime;

time_desc.len = sizeof ident->linktime_text;
time_desc.addr = ident->linktime_text;

s = sys$asctim(0, &time_desc, &eihi->eihi$q_linktime);

MOVE_FIELD(imgnam);
MOVE_FIELD(imgid);
MOVE_FIELD(linkid);
MOVE_FIELD(imgbid);
return s;
}

$
$ type IMAGE-IDENT-CALLING.COB
IDENTIFICATION DIVISION.
PROGRAM-ID. prn-test IDENT "test:1234".
DATA DIVISION.
WORKING-STORAGE SECTION.

01 image_identification.
03 imgnam_length pic s9(9) comp.
03 imgid_length pic s9(9) comp.
03 linkid_length pic s9(9) comp.
03 imgbid_length pic s9(9) comp.
03 link-time pic s9(11)v9(7) comp.
03 image-name pic x(39).
03 filler pic x.
03 image-ident pic x(15).
03 filler pic x.
03 linker-ident pic x(15).
03 filler pic x.
03 build-ident pic x(15).
03 filler pic x.
03 link-time-text pic x(23).
03 filler pic x.


PROCEDURE DIVISION.
MY_MAIN SECTION.
MAIN.
CALL "get_image_name_and_ident" USING image_identification.
DISPLAY "Image :", image-name.
DISPLAY "Ident :", image-ident.
DISPLAY "Linker:", linker-ident.
DISPLAY "Build :", build-ident.
DISPLAY "Linked:", link-time-text.
STOP RUN.

$
$ type IMAGE-IDENT-CALLING.COM
$ defin my_shared_stuff SYS$LOGIN:my_shared_stuff.exe
$ cc/deb/noopt GET_IDENT.C+sys$library:sys$lib_c.tlb/lib
$ link/debu/sysexe/share=my_shared_stuff GET_IDENT,sys$input:/opt
symbol_vector=(get_image_name_and_ident=procedure)
$
$ cob/debu/noopt IMAGE-IDENT-CALLING.COB
$ link/debu IMAGE-IDENT-CALLING, sys$input:/opt
my_shared_stuff/share
ident=some_string
build_ident=other_string
$
$ rename IMAGE-IDENT-CALLING.EXE TEST
$ run TEST
Image : IMAGE-IDENT-CALLING
Ident : SOME_STRING
Build : OTHER_STRING
Linked : 18-DEC-2006 16:50:04.41






Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

Hi Hein van den Heuvel!
>>Is this for the purpose of obtaining the image ident for the current image?<<
Yes it is!
You wrote:
>>For ALPHA ... and if you are willing to link /sysexe without actually calling system stuff, or willing to hardcode a defintion of MMG$IMGHDRBUF to be 7FFCF800 you can use the code I wrote below. I wrote the example for intended cobol usage in a shareable library.<<
Thanks for your example. It's nearly what i neet, but does ist run also in IA64 and ist there any way to avoid sharable image (linking)?
Best regards,
Kay
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

Hi Hein van den Heuvel!
>>Is this for the purpose of obtaining the image ident for the current image?<<
Yes it is!

Then there could/should be an other alternative but I haven't figured it out for I64.
Any images is activated with 6 argument, the 3rd one pointing to the image header, the 4th leading to he image file descriptor.
Works fine to get the ident on Alpha without any sys calls, if you are the main routine.
On I64, while the image descriptor is still there, the header argument is 0. :-(

This is documented in the "OpenVMS Alpha Internals, scheduling and process control" book chapter 11.5.3 "Image activation by a CLI"

Too bad for you that they did not fake that to be similar to Alpha. For the world at large that may be the right thing as few folks know how to use this and we don't need any image activation slow downs.

>> Thanks for your example. It's nearly what i neet, but does ist run also in IA64 and ist there any way to avoid sharable image

No need for the shareable, you can just link main + service. The shareable example was extra as cobol folks (no disrespect intended :-) do not always know how to use those.

No, it does not work under I64. Sorry.
I tried for a short while, but it looks like real work to figure that one out, so until someone pays me for that or I get a lot of play time' I can not help with that.

On I64 the system function IMG$ELF_DECODE_IHD might be of help. Not sure yet.

Good luck!
Hein.



Hoff
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

From within a program, there's unfortunately no supported interface to get at this stuff that I'm aware of. OpenVMS V8.2 did get some image-related flag interfaces (SET and SHOW IMAGE), but these don't show the image id and related information.

I usually embed the version details into the image using a linker option file -- or more commonly using a procedure which builds a linker options file. Based on a central data store containing the version information, I generate and set the image identification values and I set a couple of external symbols, and off I go.

ANALYZE/IMAGE (which can itself generate DCL symbols on current releases, BTW) sees the traditional values and fields from the image header (from the options file identification), and the application code can use the application-defined values (from the external symbols), the (because of the link-related procedures) the symbols and versions stay in synch, and no undocumented or non-portable interfaces are used.

Stephen Hoffman
HoffmanLabs
John Reagan
Respected Contributor

Re: ANALYZE/IMAGE callable interface?

I have I64 examples to retrieve the image information (it is scattered around the .EXE file). I'll post it next.
John Reagan
Respected Contributor

Re: ANALYZE/IMAGE callable interface?

// File: elf_imginfo.c
// Author: Hartmut Becker
// Creation Date: 24-Sep-2004
//
// Follow the Elf structure and print some VMS image note entries.
//

#include
#include
#include
#include

#include
#include

#define perrno(s) printf ("%s, errno: %d vaxc$errno: %%X%x\n", s, errno, vaxc$errno)

extern sys$asctim() ;

int format_note_section (char *filename) ;

static void decode_note_entries (char *section, int size) ;

static const char magic_plus[] = {
EHDR$K_ELFMAG0, EHDR$K_ELFMAG1, EHDR$K_ELFMAG2, EHDR$K_ELFMAG3,
EHDR$K_ELFCLASS64, EHDR$K_ELFDATA2LSB } ;

int main (int argc, char *argv[]) {
if (argc==1)
return printf ("-e-insarg, supply an ELF file.\n"), EXIT_FAILURE ;
if (format_note_section (argv[1]))
return EXIT_SUCCESS ;
return EXIT_FAILURE ;
}

int format_note_section (char *filename) {
FILE *fd ;
ELF64_EHDR the_elf_header ;
ELF64_SHDR *sh = NULL ;
char *section = NULL ;
int i ;

fd = fopen (filename, "rb") ;
if (!fd)
return perrno("-e-openerr"), 0 ;

if (fseek(fd, 0, SEEK_SET)!=0)
return perrno("-e-elfhdr"), 0 ;

if (fread(&the_elf_header, sizeof the_elf_header, 1, fd)!=1)
return perrno("-e-readehdr"), 0 ;

if (0!=strncmp((char*)&the_elf_header.ehdr$t_e_ident, magic_plus, sizeof magic_plus-1)) {
fclose (fd) ;
printf ("-e-dunno, don't understand this file format\n") ;
return 0 ;
}

sh = (ELF64_SHDR*) malloc (sizeof *sh *the_elf_header.ehdr$w_e_shnum) ;
if (fseek(fd, the_elf_header.ehdr$q_e_shoff, SEEK_SET)!=0)
return perrno("-e-seekshdr"), 0 ;
if (fread(sh, sizeof *sh*the_elf_header.ehdr$w_e_shnum, 1, fd)!=1)
return perrno("-e-readshdr"), 0 ;

for (i=1; i if (sh[i].shdr$l_sh_type==SHDR$K_SHT_NOTE) {
section = malloc (sh[i].shdr$q_sh_size) ;
if (fseek(fd, sh[i].shdr$q_sh_offset, SEEK_SET)!=0)
return perrno("-e-seeksec"), 0 ;
if (fread(section, sh[i].shdr$q_sh_size, 1, fd)!=1)
return perrno("-e-readsec"), 0 ;
decode_note_entries (section, sh[i].shdr$q_sh_size) ;
break ;
}

if (fclose(fd)!=0)
return perrno("-e-closerr"), 0 ;

return i }

static void decode_note_entries (char *section, int size) {
ELF64_NHDR *nh ;
char *owner;
char *entry;
for (nh = (ELF64_NHDR*)section ; (char*)nh-section nh= (ELF64_NHDR*)((char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7)+((nh->nhdr$q_nh_descsz+7)&~7))) {
if (nh->nhdr$q_nh_namesz>0)
owner = (char*)nh+sizeof(ELF64_NHDR) ;
else owner = "" ;
if (nh->nhdr$q_nh_descsz>0) {
if (nh->nhdr$q_nh_type == NHDR$K_NT_VMS_LINKTIME) {
char timbuf[32] ;
$DESCRIPTOR (timbuf_d, timbuf) ;
short int timlen ;
sys$asctim (&timlen,&timbuf_d,(char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7) ,0) ;
printf ("owner: '%s', linktime: %.*s\n",owner, timlen, timbuf) ;
}
else {
switch (nh->nhdr$q_nh_type) {
case NHDR$K_NT_VMS_IMGNAM:
entry = "imgnam" ;
break ;
case NHDR$K_NT_VMS_IMGID:
entry = "imgid" ;
break ;
case NHDR$K_NT_VMS_GSTNAM:
entry = "gstnam" ;
break ;
case NHDR$K_NT_VMS_IMGBID:
entry = "imgbid" ;
break ;
case NHDR$K_NT_VMS_LINKID:
entry = "linkid" ;
break ;
default:
entry = NULL ;
break ;
}
if (entry)
printf ("owner: '%s', %s: '%s'\n", owner, entry,
(char*)nh+sizeof(ELF64_NHDR) +((nh->nhdr$q_nh_namesz+7)&~7) ) ;
}
}
}
}
John Reagan
Respected Contributor

Re: ANALYZE/IMAGE callable interface?

Ooops, I forgot to click "retain format" and I couldn't figure out how to edit/delete a post. Feh!

I'll post it again.

And to answer the other question on how to get the image id of the current image... Since the ID isn't in the image header but rather contained in a ".note" buried somewhere in the image file, I don't think it is easily findable without reading the .EXE file.

// File: elf_imginfo.c
// Author: Hartmut Becker
// Creation Date: 24-Sep-2004
//
// Follow the Elf structure and print some VMS image note entries.
//

#include
#include
#include
#include

#include
#include

#define perrno(s) printf ("%s, errno: %d vaxc$errno: %%X%x\n", s, errno, vaxc$errno)

extern sys$asctim() ;

int format_note_section (char *filename) ;

static void decode_note_entries (char *section, int size) ;

static const char magic_plus[] = {
EHDR$K_ELFMAG0, EHDR$K_ELFMAG1, EHDR$K_ELFMAG2, EHDR$K_ELFMAG3,
EHDR$K_ELFCLASS64, EHDR$K_ELFDATA2LSB } ;

int main (int argc, char *argv[]) {
if (argc==1)
return printf ("-e-insarg, supply an ELF file.\n"), EXIT_FAILURE ;
if (format_note_section (argv[1]))
return EXIT_SUCCESS ;
return EXIT_FAILURE ;
}

int format_note_section (char *filename) {
FILE *fd ;
ELF64_EHDR the_elf_header ;
ELF64_SHDR *sh = NULL ;
char *section = NULL ;
int i ;

fd = fopen (filename, "rb") ;
if (!fd)
return perrno("-e-openerr"), 0 ;

if (fseek(fd, 0, SEEK_SET)!=0)
return perrno("-e-elfhdr"), 0 ;

if (fread(&the_elf_header, sizeof the_elf_header, 1, fd)!=1)
return perrno("-e-readehdr"), 0 ;

if (0!=strncmp((char*)&the_elf_header.ehdr$t_e_ident, magic_plus, sizeof magic_plus-1)) {
fclose (fd) ;
printf ("-e-dunno, don't understand this file format\n") ;
return 0 ;
}

sh = (ELF64_SHDR*) malloc (sizeof *sh *the_elf_header.ehdr$w_e_shnum) ;
if (fseek(fd, the_elf_header.ehdr$q_e_shoff, SEEK_SET)!=0)
return perrno("-e-seekshdr"), 0 ;
if (fread(sh, sizeof *sh*the_elf_header.ehdr$w_e_shnum, 1, fd)!=1)
return perrno("-e-readshdr"), 0 ;

for (i=1; i if (sh[i].shdr$l_sh_type==SHDR$K_SHT_NOTE) {
section = malloc (sh[i].shdr$q_sh_size) ;
if (fseek(fd, sh[i].shdr$q_sh_offset, SEEK_SET)!=0)
return perrno("-e-seeksec"), 0 ;
if (fread(section, sh[i].shdr$q_sh_size, 1, fd)!=1)
return perrno("-e-readsec"), 0 ;
decode_note_entries (section, sh[i].shdr$q_sh_size) ;
break ;
}

if (fclose(fd)!=0)
return perrno("-e-closerr"), 0 ;

return i }

static void decode_note_entries (char *section, int size) {
ELF64_NHDR *nh ;
char *owner;
char *entry;
for (nh = (ELF64_NHDR*)section ; (char*)nh-section nh= (ELF64_NHDR*)((char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7)+((nh->nhdr$q_nh_descsz+7)&~7))) {
if (nh->nhdr$q_nh_namesz>0)
owner = (char*)nh+sizeof(ELF64_NHDR) ;
else owner = "" ;
if (nh->nhdr$q_nh_descsz>0) {
if (nh->nhdr$q_nh_type == NHDR$K_NT_VMS_LINKTIME) {
char timbuf[32] ;
$DESCRIPTOR (timbuf_d, timbuf) ;
short int timlen ;
sys$asctim (&timlen,&timbuf_d,(char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7) ,0) ;
printf ("owner: '%s', linktime: %.*s\n",owner, timlen, timbuf) ;
}
else {
switch (nh->nhdr$q_nh_type) {
case NHDR$K_NT_VMS_IMGNAM:
entry = "imgnam" ;
break ;
case NHDR$K_NT_VMS_IMGID:
entry = "imgid" ;
break ;
case NHDR$K_NT_VMS_GSTNAM:
entry = "gstnam" ;
break ;
case NHDR$K_NT_VMS_IMGBID:
entry = "imgbid" ;
break ;
case NHDR$K_NT_VMS_LINKID:
entry = "linkid" ;
break ;
default:
entry = NULL ;
break ;
}
if (entry)
printf ("owner: '%s', %s: '%s'\n", owner, entry,
(char*)nh+sizeof(ELF64_NHDR) +((nh->nhdr$q_nh_namesz+7)&~7) ) ;
}
}
}
}
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?


Thank you John & Hartmut!

I created a (cute? clever? reckless?) variant on the code posted exploiting the "image file descriptor" which the image activator provides as 4th argument for a main image.

It contains the CHANNEL which the image activator has set set up for the main image, and the full file spec, over and beyond the image name.

Using this, one does NOT have to open the image file again. You can just CRMPSC the whole image. This variant needs to be called pretty much right upon image activation (unless you save argument 4). Consequently I don't think you need to bother with trying to map just the header of the image, as the code will only touch the header parts, and it does a DELTVA after usage to clean up the expreg VA.

My test below uses a COBOL MAIN.

How the get the real image activator argument 4 for a C program, and not the LIB$INITIAL facilitated ARGV vector is left as an excercise for the reader (It's Miller time here!).

Enjoy?

Hein van den Heuvel
HvdH Performance Consulting

$ create ELF_IMGINFO_CRMPSC.C
// File: elf_imginfo_crmpsc.c
// Author: Hein van den Heuvel vandenheuvel@gmail.com
// Creation Date: 05-Mar-2007
// Adapted from elf_imginfo.c by Hartmut Becker 24-Sep-2004
//
// Follow the Elf structure and print some VMS image note entries.
//
// Usage : stat = format_note_section ( image_file_descriptor_address )
// image_file_descriptor_address = argument 4 from main image activation.
// Output : printf to STDOUT. To be adapted to target wished.
//
// Compile with : +sys$library:sys$lib_c.tlb/lib to get ifddef.h !
//

#include
#include
#include

#include
#include
#include

#include

extern sys$asctim(), sys$crmpsc(), sys$deltva() ;

int format_note_section (IFD *ifd) ;

static void decode_note_entries (char *section, int size) ;

static const char magic_plus[] = {
EHDR$K_ELFMAG0, EHDR$K_ELFMAG1, EHDR$K_ELFMAG2, EHDR$K_ELFMAG3,
EHDR$K_ELFCLASS64, EHDR$K_ELFDATA2LSB } ;

int format_note_section (IFD *ifd) {
ELF64_EHDR *ehdr ;
ELF64_SHDR *sh = NULL ;
char *section = NULL ;
char *name ;
int i, stat, return_stat, inadr[2] ;

name = (char *) ifd + ifd->ifd$w_filnamoff ;
i = *name++; // grab length and bump pointer
printf ("File Spec: %*s\n", i, name);

inadr[0] = 0 ;
stat = sys$crmpsc ( inadr, inadr, 0, SEC$M_EXPREG, 0, 0, 0,
ifd->ifd$w_chan, 0, 0, 0, 0);
if (!(stat & 1)) {
printf ("-e-crmpsc, could not map image header\n") ;
return 0;
}

ehdr = (void *) inadr[0] ;

if (0!=strncmp((char*) &ehdr->ehdr$t_e_ident, magic_plus, sizeof magic_plus-1)) {
printf ("-e-dunno, don't understand this file format\n") ;
return 0 ;
}

sh = (ELF64_SHDR*) ((char *) ehdr + ehdr->ehdr$q_e_shoff) ;

for (i=1; i < ehdr->ehdr$w_e_shnum; i++)
if (sh[i].shdr$l_sh_type==SHDR$K_SHT_NOTE) {
section = (char *) ((char *) ehdr + sh[i].shdr$q_sh_offset) ;
decode_note_entries (section, sh[i].shdr$q_sh_size) ;
break ;
}

return_stat = iehdr$w_e_shnum ;
stat = sys$deltva (inadr, 0, 0) ;
if (!(stat & 1)) {
printf ("-e-deltva, could not UNmap image header\n") ;
return 0;
}


return return_stat ;
}

static void decode_note_entries (char *section, int size) {
ELF64_NHDR *nh ;
char *owner;
char *entry;
for (nh = (ELF64_NHDR*)section ; (char*)nh-section nh= (ELF64_NHDR*)((char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7)+((nh->nhdr$q_nh_descsz+7)&~7))) {
if (nh->nhdr$q_nh_namesz>0)
owner = (char*)nh+sizeof(ELF64_NHDR) ;
else owner = "" ;
if (nh->nhdr$q_nh_descsz>0) {
if (nh->nhdr$q_nh_type == NHDR$K_NT_VMS_LINKTIME) {
char timbuf[32] ;
$DESCRIPTOR (timbuf_d, timbuf) ;
short int timlen ;
sys$asctim (&timlen,&timbuf_d,(char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_namesz+7)&~7) ,0) ;
printf ("owner: '%s', linktime: %.*s\n",owner, timlen, timbuf) ;
}
else {
switch (nh->nhdr$q_nh_type) {
case NHDR$K_NT_VMS_IMGNAM:
entry = "imgnam" ;
break ;
case NHDR$K_NT_VMS_IMGID:
entry = "imgid" ;
break ;
case NHDR$K_NT_VMS_GSTNAM:
entry = "gstnam" ;
break ;
case NHDR$K_NT_VMS_IMGBID:
entry = "imgbid" ;
break ;
case NHDR$K_NT_VMS_LINKID:
entry = "linkid" ;
break ;
default:
entry = NULL ;
break ;
}
if (entry)
printf ("owner: '%s', %s: '%s'\n", owner, entry,
(char*)nh+sizeof(ELF64_NHDR) +((nh->nhdr$q_nh_namesz+7)&~7) ) ;
}
}
}
}
$
$
$ create test.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. prn-test IDENT "test:1234".
DATA DIVISION.
WORKING-STORAGE SECTION.
01 link-time-text pic x(24) value spaces.
01 image_file_descriptor_address POINTER.
LINKAGE SECTION.
01 a1 pic s9(11)v9(7) comp.
01 a2 pic s9(11)v9(7) comp.
01 a3 pic s9(11)v9(7) comp.
01 a4 pic s9(11)v9(7) comp.
01 a5 pic s9(11)v9(7) comp.
01 a6 pic s9(11)v9(7) comp.


PROCEDURE DIVISION USING a1,a2,a3,a4,a5,a6.
MY_MAIN SECTION.
MAIN.
SET image_file_descriptor_address TO REFERENCE OF a4.

call "format_note_section" using by value image_file_descriptor_address.
STOP RUN.
$
$ cc ELF_IMGINFO_CRMPSC.C+sys$library:sys$lib_c.tlb/lib
$ link TEST,ELF_IMGINFO_CRMPSC
$ rename TEST.EXE TMP
$ run TMP
$ run TMP/nodeb
File Spec: $9$DKB200:[HEIN]TMP.EXE;1
owner: 'IPF/VMS', imgnam: 'TEST'
owner: 'IPF/VMS', gstnam: 'TEST'
owner: 'IPF/VMS', imgid: 'test:1234'
owner: 'IPF/VMS', linktime: 5-MAR-2007 22:42:05.55
owner: 'IPF/VMS', linkid: 'Linker I02-31'


Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

Thank you all for help!
@Hein:
My c-compiler (Compaq C V6.5-001 on OpenVMS Alpha V7.3-2) has some problems with that code:
<<
$ cc ELF_IMGINFO_CRMPSC.C +sys$library:sys$lib_c.tlb/lib

sh = (ELF64_SHDR*) ((char *) ehdr + ehdr->ehdr$q_e_shoff) ;
.....................^
%CC-E-BADEXPR, Invalid expression.
at line number 61 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1

for (nh = (ELF64_NHDR*)section ; (char*)nh-section..........................^
%CC-E-BADEXPR, Invalid expression.
at line number 85 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1

nh= (ELF64_NHDR*)((char*)nh+sizeof(ELF64_NHDR)+((nh->nhdr$q_nh_
namesz+7)&~7)+((nh->nhdr$q_nh_descsz+7)&~7))) {
.................................^
%CC-E-BADEXPR, Invalid expression.
at line number 86 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1

ELF64_EHDR *ehdr ;
....^
%CC-E-UNDECLARED, In this statement, "ELF64_EHDR" is not declared.
at line number 36 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1

ELF64_EHDR *ehdr ;
................^
%CC-E-UNDECLARED, In this statement, "ehdr" is not declared.
at line number 36 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1

ELF64_SHDR *sh = NULL ;
....^
%CC-E-UNDECLARED, In this statement, "ELF64_SHDR" is not declared.
at line number 37 in file DISK$SDE:[SRC]ELF_IMGINFO_CRMPSC.C;1
...
>>
I'm not experienced enough in C, to solve that problem.

Thanks,
Kay
Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

ok!
It seems to be a Compiler-version-problem. On I64 (Compiler: HP C V7.2-001 on OpenVMS IA64 V8.3) it works!
So we have to look for an Update for our Alpha...

Thanks, Kay
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?


Kay,

This is one area where you will NOT get comparable code between the two unless, as others indicated before, you rely on your own external defintions to test / report on.

The Alpha vs I64 images are much too different and there is no VMS common routine to get you this info.

So no reason to update the compiler. John's and my recent code will only work on I64, my earlier post only on Alpha (and probably on VAX when using IHD defs vs EIHD and such.

Hein.
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

some more Free advice, worth every penny...
:-)

>>> Background: we are porting from ALPHA to I64

Just like you I want your port to have the best possible chances for success. I want OpenVMS on I64 to be a succesfull platform for you. To ensure that, your organization should seriously consider engaging with folks who can help you with that, perhaps under a support contract, or some contracting or consulting style setup.

While this whole porting thing typically is relatively straightforward, yhe questions you have raised suggest you are in it slightly over your head. No disrespect intended. We all have our areas of strength and new thing to learn. But first there was that question on the shareable library. And now the 'blaming' on the compiler for what is just a poor environment setup.

Clearly there is an include library missing. If that is not clear to the folks working this port, then they should not be doing that particular part of the work. Sorry to be so blunt about it.

I just verified, and Hartmut's example code works fine on a VMS V7.2-1 Alpha with a V6.2-003 C, or any random PC for that matter.

To make it work I did need to provide an 'elfdef.h' and 'elfdatyp.h' which you can snarf from a sys$library:SYS$STARLET_C.TLB on any 8.2 or better OpenVMS system.

Now the code I provided can only be run on I64 as I indicated before. This is because because, as per suggestion, it obtains the indent for the running image.

btw... I since learned that one pretty much needs to map the whole image, or map selectively, as those ident section live close to the end of file.

Kindest regards,

Hein van den Heuvel
HvdH Performance Consulting


Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

Thanks Hein!
Now, we have to discuss in our team the possible soloutions while observing the facts:
- We need to run both architectures in a Cluster for sereral months
- We have to change roundabout 100 Programms. If we have to, with conditionalized code.

In my opinion a combination of your and Hartmut's examble could do the job, but we have to discuss that.

Best regards,
Kay Dolle
Hein van den Heuvel
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

Right. But you also may want to set a big step back and try to remember WHY yo needed that ident. And how does it get there?
If it is a line in the .OPT file then that line could be changed to become an object module. Instead of priting/comparing strings in the code you could call a function in that ident object reporting its ident or comparing its hard-coded ident with lookup in an (indexed)file.

Regards,
Hein.

Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

I'm not shure that i understand you right, but if you suggest, that the string with the ident could be a constant in the main program, then the effort in develloping in our SDE is the same as before.
One reason why we need the indent is to compare the Version of the running Program with the allowed Version, we would like the users have to use. In our EDP the users start a dialog-program in the morning and leave it, when going home. With that function we have the possibility to instal a new program-version an be shure the users use it when the program is in a defined state (that state, when the program can be terminated without data loss)

With the already existing function for the indexed-file-lookup (allowed Version) we should put that on the list with possible souloutions!

Thanks
Kay
Hoff
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

Insert the declaration of an external variable or two directly into the options file, and reference it (them) in your code.

You could use KD_VERSION_MAJOR and KD_VERSION_MINOR, for instance.

No undocumented stuff.

No image file headers.

Fully portable.

Add the external references into the code where required, and you can access the constants from the LINKER options file directly.

You're done.

If you wanted to get a little fancier, a couple dozen lines of DCL can easily generate the options file contents on the fly, and can generate both the external symbols used by the program, and the image identification string. This would allow you to have a three line option file, with the two externals and the matching ident string.

Again, all fully documented, fully portable, platform-independent, and fully supported.

Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

I found that syntax
SYMBOL=name,n
with n seems to be an integer!? All trys to place a string caused an %LINK-F-OPTSYNERR". I didn't find an example for that.
What is need to have access to that symbol in COBOL. How i understand the manual i should delare the variable with
external
The compiler like it, but at runtime the variable is hex(0).
Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

I fixed the last problem with
name PIC S9(6) comp value is external name
Also the compiler accepts that with a "comp"-Variable - means integer...
Anyone an idea for a string?
Kris Clippeleyr
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

Kay,

> Anyone an idea for a string?

I haven't got an example in COBOL, but I have used the technique described by Hoff for years from C.
In the .OPT file, e.g.

SYMBOL=QVER,%x332E3056

The hex-value, converted to ASCII and read from right to left is "V0.3"

In my C code, I declare a global value:

globalvalue int QVER;

Then, I declare a descriptor like this:

int vers = QVER;
struct dsc$descriptor_s dsc = {
(unsigned short int) sizeof ( int )
, (unsigned char) DSC$K_DTYPE_T
, (unsigned char) DSC$K_CLASS_S
, (char *) &vers
}

This descriptor I then use in a call to lib$put_output:

int sts;
sts = lib$put_output ( &dsc );

Hope this helps,
Kris (aka Qkcl)

I'm gonna hit the highway like a battering ram on a silver-black phantom bike...
Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

I have found the way we don't need the string. Our version numbers are like "Vn.nn" with no Caracters behind "V". So it is only the definition of a structure and one "move" in COBOL to retreive the desired format.

Thanks for all for help!
best regards,
Kay
Hoff
Honored Contributor

Re: ANALYZE/IMAGE callable interface?

I've always used integers, since it's easier to use same for comparisons than a text string, and it's easier to construct a text string than to parse it.

For cases where I needed a text string (such as for cases of human display), I stuff the same values into a standard print statement enveloped with the appropriate prettiness.
Kay Dolle
Advisor

Re: ANALYZE/IMAGE callable interface?

Thanks again to all!
We'll use the solution with the gloabl symbols in the opt-file. It is easy to use, portable and adaptable with less effort.
Best regards,
Kay Dolle