• Advertisement
Sign in to follow this  

Fun code!

This topic is 4764 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Had fun figuring this out at work. I'm sure lots of people will enjoy this :). Only tested on VC7, so use at your own risk.
#pragma const_seg(".qdata")
#pragma comment(linker, "/merge:.qdata=.rdata")
#pragma const_seg(".rdataZ")
#pragma comment(linker, "/merge:.rdataZ=.rdata")
#pragma const_seg()

bool is_constant_address(const volatile void *address)
{
	static __declspec(allocate(".qdata")) char x_read_only_data_start= NULL;
	static __declspec(allocate(".rdataZ")) char x_read_only_data_end= NULL;

	return address>=(const volatile void *)&x_read_only_data_start && address<(const volatile void *)&x_read_only_data_end;
}


MSN

Share this post


Link to post
Share on other sites
Advertisement
Okay, I think I've got it.

#pragma const_seg([segment-name]) causes constant data allocated following the #pragma to be placed in the section identified by segment-name. (There's a second parameter for #pragma const_seg, but it's now ignored).

#pragma comment(linker, string) emits string as an option to the linker. /MERGE .from=.to merges two new executable (NE) segments (which may contain either code or data) and names the new segment to. .rdata is one of the reserved segment names, so the two new segments .qdata and .rdataZ are being appended to it.

Because .qdata and .rdataZ are declared in succession, they are adjacent, with .qdata coming "first" in memory. This is essential for the workings of the is_constant_address() function. By testing if the supplies address lies between x_read_only_data_start, which is synonymous with the top of .qdata, and x_read_only_data_end, which is synonymous with the top of .rdataZ, or the end of .qdata, is_constant_address() effectively tests whether the address was allocated in .qdata, which would make it const.

The only part I'm iffy on is the effect of #pragma const_seg(). The parameters are optional, but there is no remark as to what occurs when they are both omitted. My guess is that it restores the default, which is why __declspec(allocate([section])) is used on x_read_only_data_start and x_read_only_data_end, which, of course, are static so that they maintain their values and addresses and/or avoid pointless redefinition for each invocation.

Share this post


Link to post
Share on other sites
Quote:

Because .qdata and .rdataZ are declared in succession, they are adjacent, with .qdata coming "first" in memory.


I belive the convention is for the linker to arange all sections of the same type (in this case .rdata) into alphabetical order. Thus the default section is called ".rdata" which the linker puts all the real const data into. So the order goes:

.qdata //containing the starter marker
.rdata //the "real" section with all the programs const data
.rdataZ //containing the end marker

Quote:

The only part I'm iffy on is the effect of #pragma const_seg()


It just puts the linker back into "normal" mode so any unmarked data gets put into the default .rdata section (else I think it would get put into the last section you named, but I'm not certain about that).

Alan

Share this post


Link to post
Share on other sites
Quote:
Original post by Alan Kemp
I belive the convention is for the linker to arange all sections of the same type (in this case .rdata) into alphabetical order. Thus the default section is called ".rdata" which the linker puts all the real const data into. So the order goes:

.qdata //containing the starter marker
.rdata //the "real" section with all the programs const data
.rdataZ //containing the end marker
Ah. Interesting. Need to brush up on that.

Quote:
It just puts the linker back into "normal" mode so any unmarked data gets put into the default .rdata section (else I think it would get put into the last section you named, but I'm not certain about that).
Yeah, that's what I thought, too.

Share this post


Link to post
Share on other sites
Quote:
Original post by Alan Kemp
Quote:

The only part I'm iffy on is the effect of #pragma const_seg()


It just puts the linker back into "normal" mode so any unmarked data gets put into the default .rdata section (else I think it would get put into the last section you named, but I'm not certain about that).

Alan


Yup. When I was testing this code, I forgot to put in the last #pragma const_seg(), so all the constant strings were being placed after x_read_only_data_end.

MSN

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement