iss #1219 #1223 #1224 reference ignored in name from address (#1222)

* #1219 added code to check reference mod bit in ClassicCheckPointAgent::getCompositeSubReference, use reference width instead of size.

* #1219 refactor getCompositeSubReference for readability

* #1219 and #1223 add reference width to mod bits in ICG

* check for mod bits in TRICK_STRUCTURED section, refactor function

* #1219 adding MM_ref_name_from_address tests

* #1224 fix logic for offset into arrayed struct

closes #1219 closes #1223 closes #1224 

Co-authored-by: Fennell, Scott P 263712616 <scott.p.fennell@nasa.gov>
This commit is contained in:
Scott Fennell 2022-02-08 09:59:26 -06:00 committed by GitHub
parent 017a5aecf5
commit 0d60ef0b6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 295 additions and 151 deletions

View File

@ -98,6 +98,12 @@ typedef struct ATTRIBUTES_tag {
bit 0 = c++ reference var
bit 1 = c++ static var
bit 2 = "--" units
bit 3-8:
if c++ reference bit is set, width of reference attribute.
else not set.
Why: because `size` is the size of the type, not the reference
reference is the size of a pointer because of compiler implementations, but
is not enforced by C++ standard (could change).
bit 31 = deprecated var */
long offset; /**< -- Offset in bytes of this parameter from beginning of data structure */

View File

@ -76,7 +76,8 @@ void PrintFileContents10::print_field_attr(std::ostream & ostream , FieldDescri
ostream << ", sizeof(" << fdes.getTypeName() << ")" ;
}
ostream << ", 0, 0, Language_CPP" ; // range_min, range_max, language
ostream << ", " << fdes.isReference() + (fdes.isStatic() << 1) + (fdes.isDashDashUnits() << 2) << "," << std::endl ; // mods
// mods (see attributes.h for descriptions)
ostream << ", " << fdes.isReference() + (fdes.isStatic() << 1) + (fdes.isDashDashUnits() << 2) + (fdes.isReference() ? (((fdes.getFieldWidth() / 8) & 0x3F) << 3) : 0) << "," << std::endl ; // mods
if ( fdes.isBitField() ) {
// For bitfields we need the offset to start on 4 byte boundaries because that is what our
// insert and extract bitfield routines work with.

View File

@ -143,57 +143,32 @@ void Trick::ClassicCheckPointAgent::write_decl(std::ostream& chkpnt_os, ALLOC_IN
}
}
// STATIC FUNCTION
/*
Given an address, that is within the bounds of a composite
object (i.e., a struct or class instance), return the corresponding sub-name.
/*
Given an offset, that is within the bounds of a composite
object (i.e., a struct or class instance), return the corresponding
ATTRIBUTES pointer (singular).
A return value of NULL indicates an error occured. Note that this is not
the same as a return value of "", which is valid.
The following BNF production describes a valid sub-reference:
<sub_reference> --> ""
| "+" + <offset>
| "[" + <index>+ "]" + <sub_reference>
| "." + <member_name> + <sub_reference>
<offset> is an integer. It is the the reference offset minus the offset of
the last data member.
<index> is an integer. It is an array index.
<member_name> is a name of a member of the given composite type.
Helper function for getCompositeSubReference.
.
*/
static char *getCompositeSubReference(
void* reference_address, /* Address we are looking for */
ATTRIBUTES** left_type, /* Attributes of type we are looking for */
void* structure_address, /* Address of struct we are in */
ATTRIBUTES* A /* Attributes of current struct we are in */
) {
int i = 0, j;
long offset;
int my_index[9];
char* ret;
char reference_name[512];
int size, last_size;
int temp_size;
char* rAddr = (char*)reference_address;
char* sAddr = (char*)structure_address;
long referenceOffset = (long)rAddr - (long)sAddr;
if ( referenceOffset < 0) {
message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Address to find is less than struct address.\n") ;
return NULL;
}
static ATTRIBUTES* findMember(ATTRIBUTES* A, long referenceOffset) {
int i = 0;
int j;
int temp_size;
/* Find the member which contains the address pointed to by rAddr */
while ((A[i].name[0] != '\0')) {
// Calculate the size (temp_size) of the referenced member variable.
if (A[i].num_index != 0) {
// if mod bit 0 is set, A[i] is a reference. Width of reference is stored
// in mod bits 3-8. We could use sizeof(void*), but that is implementation
// specific and not required by C++ standard.
if ((A[i].mods & 1) == 1) {
temp_size = ((A[i].mods >> 3) & 0x3F);
// Calculate the size (temp_size) of the referenced member variable.
} else if (A[i].num_index != 0) {
// if size of last valid index is 0, then we are looking at a pointer
if (A[i].index[A[i].num_index - 1].size == 0) {
temp_size = sizeof(void*);
} else {
@ -220,7 +195,66 @@ static char *getCompositeSubReference(
}
}
if (A[i].name[0] == '\0') {
return &(A[i]);
}
// STATIC FUNCTION
/*
Given an address, that is within the bounds of a composite
object (i.e., a struct or class instance), store the corresponding sub-name
in reference_name buffer and return.
A return value of 1 indicates an error occured. A return value of 0 indicates
success.
The following BNF production describes a valid sub-reference:
<sub_reference> --> ""
| "+" + <offset>
| "[" + <index>+ "]" + <sub_reference>
| "." + <member_name> + <sub_reference>
<offset> is an integer. It is the the reference offset minus the offset of
the last data member.
<index> is an integer. It is an array index.
<member_name> is a name of a member of the given composite type.
*/
static int getCompositeSubReference(
void* reference_address, /* Address we are looking for */
ATTRIBUTES** left_type, /* Attributes of type we are looking for */
void* structure_address, /* Address of struct we are in */
ATTRIBUTES* A, /* Attributes of current struct we are in */
char* reference_name /* destination buffer of composite subreference */
) {
int j, k, m;
long offset;
int my_index[9];
int ret;
int size, last_size;
int temp_size;
char* rAddr = (char*)reference_address;
char* sAddr = (char*)structure_address;
long referenceOffset = (long)rAddr - (long)sAddr;
// selected ATTRIBUTES stucture from A (singular)
ATTRIBUTES* Ai;
if ( referenceOffset < 0) {
message_publish(MSG_ERROR, "Checkpoint Agent ERROR: Address to find is less than struct address.\n") ;
return 1;
}
// Find the structure member that corresponds to the reference address.
// If name is empty, we have failed.
Ai = findMember(A, referenceOffset);
/******If failed to find member, set reference_name to offset only and return ****/
if (Ai->name[0] == '\0') {
/* If we fail to find a member corresponding to the reference address,
it must mean that the ATTRIBUTES don't contain a description for
that particular member, i.e., it was **'ed out. In this case, we can only
@ -229,119 +263,129 @@ static char *getCompositeSubReference(
if (referenceOffset == 0) {
reference_name[0] = '\0' ;
} else if (referenceOffset > 0) {
sprintf(reference_name," + %ld", referenceOffset);
sprintf(reference_name, " + %ld" , referenceOffset);
} else {
return NULL; // ERROR
return 1; // ERROR
}
return 0;
}
/******************************************************************************/
/* We found a member corresponding to the reference address, so print it's name. */
sprintf(reference_name, ".%s", Ai->name);
/* If the referenced member variable is an intrinsic type */
if (Ai->type != TRICK_STRUCTURED) {
/* If the reference address is non-array or a pointer, return reference_name as is */
if((Ai->num_index == 0) || (Ai->index[0].size == 0)) {
return 0;
}
} else {
/* else, rAddr is pointing to an array, determine its dimensions and determine
the element pointed to by rAddr. Then print the index and return */
// We found a member corresponding corresponding to the reference address, so print it's name.
sprintf(reference_name, ".%s", A[i].name);
offset = (long) rAddr - ((long) sAddr + Ai->offset);
size = last_size = Ai->size;
// If the referenced member variable is an intrinsic type.
if (A[i].type != TRICK_STRUCTURED) {
/* If rAddr in pointing to an array then determine its dimensions and determine the element pointed to by rAddr */
if ((A[i].num_index != 0) && (A[i].index[0].size != 0)) {
offset = (long) rAddr - ((long) sAddr + A[i].offset);
size = last_size = A[i].size;
/* Calculate the number of fixed dimensions. */
int num_fixed_dims = 0;
for (j = 0; j < A[i].num_index; j++) {
if (A[i].index[j].size > 0) {
num_fixed_dims++;
}
}
// Calculate the array indices for the right-side.
for (j = num_fixed_dims - 1; j >= 0; j--) {
size *= A[i].index[j].size;
if(!size) {
std::cerr << "Checkpoint Agent " << __FUNCTION__ << " ERROR: divide by zero during array indices calculation" << std::endl;
return NULL;
}
my_index[j] = (int) ((offset % size) / last_size);
offset -= last_size * my_index[j];
last_size = size;
}
for (j = 0; j < num_fixed_dims; j++) {
sprintf(&reference_name[strlen(reference_name)], "[%d]", my_index[j]);
}
/* Calculate the number of fixed dimensions. */
int num_fixed_dims = 0;
for (j = 0; j < Ai->num_index; j++) {
if (Ai->index[j].size > 0) {
num_fixed_dims++;
}
}
// Calculate the array indices for the right-side.
for (j = num_fixed_dims - 1; j >= 0; j--) {
size *= Ai->index[j].size;
if(!size) {
std::cerr << "Checkpoint Agent " << __FUNCTION__ << " ERROR: divide by zero during array indices calculation" << std::endl;
return 1;
}
my_index[j] = (int) ((offset % size) / last_size);
offset -= last_size * my_index[j];
last_size = size;
}
for (j = 0; j < num_fixed_dims; j++) {
sprintf(&reference_name[strlen(reference_name)], "[%d]", my_index[j]);
}
return 0;
}
/******** TRICK_STRUCTURED ****************************************************/
/* if it is a reference, do nothing and return */
if ((Ai->mods & 1) == 1) { // Ai->type == TRICK_STRUCTURED
return 0;
}
/*if member is an unarrayed struct, continue to call getCompositeSubReference.*/
if (Ai->num_index == 0) {
char buf[256];
ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset, (ATTRIBUTES *) Ai->attr, buf);
if (ret == 0) {
sprintf(&reference_name[strlen(reference_name)],"%s", buf);
} else {
return 1; // ERROR.
}
return 0;
}
/* Member is an unarrayed struct, continue to call getCompositeSubReference. */
if (A[i].num_index == 0) {
/***** If the member is not a pointer do nothing and return *******************/
if (Ai->index[0].size == 0) {
return 0;
}
ret = getCompositeSubReference( rAddr, left_type, sAddr + A[i].offset, (ATTRIBUTES *) A[i].attr);
/*********** Member is an arrayed struct **************************************/
if (ret != NULL) {
sprintf(&reference_name[strlen(reference_name)],"%s", ret);
free(ret);
} else {
// ERROR.
}
offset = (long) rAddr - ((long) sAddr + Ai->offset);
size = last_size = Ai->size;
} else {
/* Calculate the indices into the array */
for (j = Ai->num_index - 1; j >= 0; j--) {
if (Ai->index[j].size != 0) {
size *= Ai->index[j].size;
}
my_index[j] = (int) ((offset % size) / last_size);
offset -= last_size * my_index[j];
last_size = size;
}
/* Member is an arrayed struct, or a pointer to a struct ... */
offset = (long) rAddr - ((long) sAddr + A[i].offset);
size = last_size = A[i].size;
for (j = 0; j < Ai->num_index; j++) {
sprintf(&reference_name[strlen(reference_name)], "[%d]", my_index[j]);
}
/* Note that there's nothing more to do for a pointer to a struct. */
/* if left_type specifies the current member, stop here */
if ( (left_type != NULL) && (*left_type != NULL) && (Ai->attr == (*left_type)->attr)) {
return 0;
}
if (A[i].index[0].size != 0 ) {
/**** Go find the subreference for the arrayed struct member and append *********/
/* Member is an arrayed struct. */
/* Calculate the indices into the array */
for (j = A[i].num_index - 1; j >= 0; j--) {
if (A[i].index[j].size != 0) {
size *= A[i].index[j].size;
}
my_index[j] = (int) ((offset % size) / last_size);
offset -= last_size * my_index[j];
last_size = size;
}
/* get the offset into the array that rAddr points to */
offset = 0;
for (j = 0; j < Ai->num_index; j++) {
m = my_index[j];
for(int k = j + 1; m && (k < Ai->num_index); k++) {
m *= Ai->index[k].size;
}
offset += m*Ai->size;
}
if ( (left_type != NULL) && (*left_type != NULL) && (A[i].attr == (*left_type)->attr)) {
{
char buf[256];
ret = getCompositeSubReference( rAddr, left_type, sAddr + Ai->offset + offset, (ATTRIBUTES *) Ai->attr, buf);
for (j = 0; j < A[i].num_index; j++) {
sprintf(&reference_name[strlen(reference_name)], "[%d]", my_index[j]);
}
} else {
/* get the offset into the array that rAddr points to */
offset = A[i].size;
for (j = 0; j < A[i].num_index; j++) {
offset *= my_index[j];
}
for (j = 0; j < A[i].num_index; j++) {
sprintf(&reference_name[strlen(reference_name)], "[%d]", my_index[j]);
}
ret = getCompositeSubReference( rAddr, left_type, sAddr + A[i].offset + offset, (ATTRIBUTES *) A[i].attr);
if (ret != NULL) {
sprintf(&reference_name[strlen(reference_name)], "%s", ret);
free(ret);
} else {
return NULL; // ERROR
}
}
}
}
if (ret == 0) {
sprintf(&reference_name[strlen(reference_name)], "%s", buf);
} else {
return 1; // ERROR
}
}
return (strdup(reference_name));
return 0;
}
@ -353,15 +397,15 @@ std::string Trick::ClassicCheckPointAgent::get_var_name( void* addr,
void* struct_addr,
std::string name,
ATTRIBUTES** left_type) {
char *ret;
char reference_name[256];
int ret;
std::string var_name;
var_name = name;
ret = getCompositeSubReference( addr, left_type, struct_addr, A);
ret = getCompositeSubReference( addr, left_type, struct_addr, A, reference_name );
if (ret != NULL) {
var_name += ret;
free(ret);
if (ret == 0) {
var_name += reference_name;
} else {
std::stringstream ss;
ss << "Checkpoint Agent ERROR: Unable to create a subreference of variable \"" << name << "\"."

View File

@ -54,3 +54,73 @@ TEST_F(MM_ref_name_from_address, test4) {
EXPECT_EQ("&udt2_var2[1].udt1_var.udt_p", ref_name);
}
#if __GNUC__ > 4
TEST_F(MM_ref_name_from_address, test5) {
int i;
double d;
UDT3 udt3_st = {i, false, d};
UDT3* udt3_p1 = &udt3_st;
memmgr->declare_extern_var(udt3_p1, "UDT3 udt3_st");
std::string ref_name = memmgr->ref_name_from_address(&(udt3_p1->bl));
EXPECT_EQ("&udt3_st.bl", ref_name);
}
TEST_F(MM_ref_name_from_address, test6) {
int i;
double d;
bool b;
UDT2 udt2_st;
UDT3 udt3_st = {i, false, d};
UDT4 udt4_st = {udt3_st, &b, udt2_st, 2.0};
UDT4 * udt4_p1 = & udt4_st;
memmgr->declare_extern_var(udt4_p1, "UDT4 udt4_st");
std::string ref_name = memmgr->ref_name_from_address(udt4_p1);
EXPECT_EQ("&udt4_st.udt3_ref", ref_name);
}
TEST_F(MM_ref_name_from_address, test7) {
int i;
double d;
bool b;
UDT2 udt2_st;
UDT3 udt3_st = {i, false, d};
UDT4 udt4_st = {udt3_st, &b, udt2_st, 2.0};
UDT4 * udt4_p1 = & udt4_st;
memmgr->declare_extern_var(udt4_p1, "UDT4 udt4_st");
std::string ref_name = memmgr->ref_name_from_address(&(udt4_p1->bl_p));
EXPECT_EQ("&udt4_st.bl_p", ref_name);
}
TEST_F(MM_ref_name_from_address, test8) {
int i;
double d;
bool b;
UDT2 udt2_st;
UDT3 udt3_st = {i, false, d};
UDT4 udt4_st = {udt3_st, &b, udt2_st, 2.0};
UDT4 * udt4_p1 = & udt4_st;
memmgr->declare_extern_var(udt4_p1, "UDT4 udt4_st");
std::string ref_name = memmgr->ref_name_from_address(&(udt4_p1->dbl));
EXPECT_EQ("&udt4_st.dbl", ref_name);
}
#endif
TEST_F(MM_ref_name_from_address, test9) {
UDT5 udt5_st;
UDT5* udt5_p1 = (UDT5*)memmgr->declare_var("UDT5 udt5_var");
std::string ref_name = memmgr->ref_name_from_address(&(udt5_p1->udt2_2d_arr[2][1].x));
EXPECT_EQ("&udt5_var.udt2_2d_arr[2][1].x", ref_name);
}

View File

@ -2,15 +2,38 @@
PURPOSE: (Testing)
*/
typedef struct udt1 {
double x;
struct udt1 *udt_p;
double *dbl_p;
} UDT1;
struct UDT1 {
double x;
UDT1* udt_p;
double* dbl_p;
};
typedef struct udt2 {
struct UDT2 {
UDT1 udt1_var;
double x;
struct udt1 *udt_p;
double *dbl_p;
} UDT2;
UDT1* udt_p;
double* dbl_p;
};
struct UDT3 {
int& i_r;
bool bl;
double& dbl_r;
UDT3() = delete;
};
struct UDT4 {
UDT3& udt3_ref;
bool* bl_p;
UDT2& udt2_ref;
double dbl;
UDT4() = delete;
};
struct UDT5 {
double y;
UDT2 udt2_2d_arr[3][4];
};