File: auto_zlink.c

package info (click to toggle)
fis-gtm 6.2-000-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 30,784 kB
  • ctags: 42,554
  • sloc: ansic: 358,483; asm: 4,847; csh: 4,574; sh: 2,261; awk: 200; makefile: 86; sed: 13
file content (117 lines) | stat: -rw-r--r-- 4,519 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/****************************************************************
 *								*
 *	Copyright 2003, 2014 Fidelity Information Services, Inc	*
 *								*
 *	This source code contains the intellectual property	*
 *	of its copyright holder(s), and is made available	*
 *	under a license.  If you do not know the terms of	*
 *	the license, please stop and do not read further.	*
 *								*
 ****************************************************************/

#include "mdef.h"

#include "gtm_string.h"

#include "urx.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "op.h"
#include <auto_zlink.h>

GBLREF unsigned char    *obpt;          /* output buffer index */
GBLREF stack_frame	*frame_pointer;

IA64_ONLY(GBLREF uint8 		imm14;)
IA64_ONLY(GBLREF char 		asm_mode;)

/* Due to the complex instruction set of x86_64, we require a function to implement the macro VALID_CALLING_SEQUENCE
 * and this function will calculate both the offsets (rtnhdr & labaddr) and store them into these global variables.
 */
#if defined(__x86_64__) || defined(__MVS__) || defined(Linux390)
GBLDEF int4		rtnhdr_off;
GBLDEF int4		labaddr_off;
#endif

error_def	(ERR_LABELUNKNOWN);
error_def	(ERR_ROUTINEUNKNOWN);

rhdtyp	*auto_zlink(mach_inst *pc, lnr_tabent ***line)
{
	lnk_tabent	*A_rtnhdr;
	lnk_tabent	*A_labaddr;
	mstr		rname;
	mident_fixed	rname_buff;
	mval		rtn;
	rhdtyp		*rhead;
	urx_rtnref	*rtnurx;

#	ifdef USHBIN_SUPPORTED
	/* With the current autorelink multi-opcode call (OP_RHD_EXT and OP_LAB_EXT prior to actual call), auto_zlink()
	 * isn't really at all used but this is likely to change in the next release which streamlines some of this so
	 * for now, this routine is not being nixed.
	 */
	USHBIN_ONLY(assertpro(FALSE));
#	else
/* (ASSUMPTION)
 * The instructions immediately preceding the current mpc form a transfer table call.
 *	There will be two arguments to this call:
 *		the address of a routine header and
 *		the address of a pointer to a value which is the offset from the beginning of the routine header
 *			to the address of the first instruction to be executed in the routine to be called, as
 *			specified by the [label][+offset] field (or the beginning of the routine if label and
 *			offset are not specified)
 *	We compute the linkage table offsets of both parameters by disassembling the load instructions that were
 *	generated to load arguments. The entire instruction sequence is platform dependent (see auto_zlink_sp.h).
 *
 *	N.B., the instruction sequence above occurs in compiled object modules; in direct mode, the argument
 *	registers are loaded via "load" instructions.  However, this routine should never be invoked from direct
 *	mode because the applicable routine should have been ZLINK'ed by prior calls to op_labaddr and op_rhdaddr.
 */
	NON_IA64_ONLY(assertpro(VALID_CALLING_SEQUENCE(pc)));
	/* Calling sequence O.K.; get address(address(routine header)) and address(address(label offset)).  */
#	ifdef __ia64 /* __ia64 */
	{
		uint8 imm;
		int8 *buf2, i;
		ia64_bundle  bundle;
		uint8 dummy, dummy2, dummy1;
		int isMovl = 0;

		RTNHDR_PV_OFF(pc,imm);
		A_rtnhdr  = (lnk_tabent *)(imm + frame_pointer->ctxt);
		dummy1 = dummy; /* For silly compiler warning */
		LABADDR_PV_OFF(pc, imm);
		A_labaddr = (lnk_tabent *)(imm + frame_pointer->ctxt);
	}
#	endif /* __ia64 */
        NON_IA64_ONLY(A_rtnhdr  = (lnk_tabent *)(RTNHDR_PV_OFF(pc) + frame_pointer->ctxt);)
        NON_IA64_ONLY(A_labaddr = (lnk_tabent *)(LABADDR_PV_OFF(pc) + frame_pointer->ctxt);)
	if (azl_geturxrtn((char *)A_rtnhdr, &rname, &rtnurx))
	{
		assert(rname.len <= MAX_MIDENT_LEN);
		assert(0 != rname.addr);
		/* Copy rname into local storage because azl_geturxrtn sets rname.addr to an address that is
		 * free'd during op_zlink and before the call to find_rtn_hdr.
		 */
                memcpy(rname_buff.c, rname.addr, rname.len);
                rname.addr = rname_buff.c;
		assert(0 != rtnurx);
		assert(azl_geturxlab((char *)A_labaddr, rtnurx));
		assert(0 == find_rtn_hdr(&rname));
		rtn.mvtype = MV_STR;
		rtn.str.len = rname.len;
		rtn.str.addr = rname.addr;
		op_zlink(&rtn, 0);
		if (0 != (rhead = find_rtn_hdr(&rname)))
		{	/* Pull the linkage table reference out and return it to caller */
			*line = (lnr_tabent **)(A_labaddr->ext_ref);
			if (0 == *line)
				rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_LABELUNKNOWN);
			return rhead;
		}
	}
	rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ROUTINEUNKNOWN);
#	endif		/* ifdef USHBIN_SUPPORTED */
	return NULL;	/* Compiler happiness phase */
}