Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #10758 > unrolled thread

Inconsistent results between char/short/int

Started byGuillaume Dargaud <use_the_contact_form@www.gdargaud.net>
First post2011-09-23 15:46 +0200
Last post2011-09-29 21:57 +0000
Articles 8 — 6 participants

Back to article view | Back to comp.lang.c


Contents

  Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-23 15:46 +0200
    Re: Inconsistent results between char/short/int Noob <root@127.0.0.1> - 2011-09-23 16:44 +0200
    Re: Inconsistent results between char/short/int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-23 17:16 +0100
      Re: Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-29 14:53 +0200
    Re: Inconsistent results between char/short/int Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-09-23 20:21 -0400
      Re: Inconsistent results between char/short/int Nobody <nobody@nowhere.com> - 2011-09-24 18:26 +0100
        Re: Inconsistent results between char/short/int Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> - 2011-09-29 14:50 +0200
      Re: Inconsistent results between char/short/int Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-09-29 21:57 +0000

#10758 — Inconsistent results between char/short/int

FromGuillaume Dargaud <use_the_contact_form@www.gdargaud.net>
Date2011-09-23 15:46 +0200
SubjectInconsistent results between char/short/int
Message-ID<j5i2ki$72q$1@ccpntc8.in2p3.fr>
Hello all,
I know it's frowned upon to post system-specific code here, but I'd like to 
know if the error is in my C code (wrong pointer manipulation), in my 
handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC 
processor).

Basically I get different results when trying to read the memory as a single 
byte, as a short or as an int (the only one that returns correct results).

Code is below.
Basically only the first 2 are correct:

# ./Peek -w 0x81600000 0x10
81600000~48006000: 00000000 00000000 00000000 00000000  ................
81600010~48006010: 00000000 00000000 00000000 80000000  ................
81600020~48006020: 000000d0 00000000 00000021 00000000  ................
81600030~48006030: 00000000 00000000 00000000 00000000  ................

# ./Peek -w 0x81600010 0xC
81600010~48006010: 00000000 00000000 00000000 80000000  ................
81600020~48006020: 000000d0 00000000 00000021 00000000  ................
81600030~48006030: 00000000 00000000 00000000 00000000  ................

# ./Peek -w 0x81600001 0x10
81600001~48006001: 00000000 00000000 00000000 00000000  ................
81600011~48006011: 00000000 00000000 00000000 00000000  ................
81600021~48006021: 00000000 00000000 00000000 00000000  ................
81600031~48006031: 00000000 00000000 00000000 00000000  ................

# ./Peek -s 0x81600000 0x20
81600000~48006000: 0000 0000  0000 0000  0000 0000  0000 0000
................
81600010~48006010: 0000 0000  0000 0000  0000 0000  0000 0000  
................
81600020~48006020: 0000 0000  0000 0000  0000 0000  0000 0000  
................
81600030~48006030: 0000 0000  0000 0000  0000 0000  0000 0000  
................

# ./Peek -b 0x81600000 0x40
81600000~48006000: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  
................
81600010~48006010: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  
................
81600020~48006020: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  
................
81600030~48006030: 00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  
................


// Note: this is strictly 32-bit code with 32-bit pointers
// Note 2: only root can use this program

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iso646.h>
#include <errno.h>

#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

#include <linux/types.h>

static char Str[]="%s [-b|s|w] address [nb]\n"
	"Physical memory dump (using /dev/mem and mmap)\n"
	"-b:   byte dump (default)\n"
	"-s:   short dump\n"
	"-w:   word dump\n"
	"nb:   number of values to dump (default 1 which prints 16 
bytes, 8 short or 4 words, must be less than 4kb)\n"
	"Notes: You can use 0x notation for address and nb. Only root 
can access /dev/mem.\n";

#define Usage { fprintf(stderr, Str, argv[0]); return 1; }

// Display printable chars as themselves, or replaces non-printable by '.'
#define F(ch, offset) ( isprint(*((unsigned char*)(ch)+(offset))) ? 
*((unsigned char*)(ch)+(offset)) : '.' )

#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

int main (int argc, char *argv[]) {
	int Bits=8;	// 8, 16 or 32
	unsigned int Address=0;
	unsigned int Nb=1, NbBytes;
	int i, Done=0;
	unsigned int Phy;
	int memfd=0, Ret=0;
	void *mapped_base=NULL, *Virt=NULL;
	
	if (sizeof(void*)!=sizeof(int)) {
		fprintf(stderr, "This can run only on 32-bit 
systems with 32-bit pointers\n"); return 1; }
	
	if (argc<2 or argc>4) Usage;
	
	for (i=1; i<argc; i++) {
		     if (strcmp(argv[i], "-b")==0) Bits=8;
		else if (strcmp(argv[i], "-s")==0) Bits=16;
		else if (strcmp(argv[i], "-w")==0) Bits=32;
		else if (argv[i][0]!='-') { 
			if (Done) {
				if (argv[i][0]=='0' and 
argv[i][1]=='x') Nb=strtoul(argv[i]+2, NULL, 16); 
				else Nb=atoi(argv[i]); 
			}
			else {
				if (argv[i][0]=='0' and 
argv[i][1]=='x') Address=strtoul(argv[i]+2, NULL, 16); 
				else 
Address=atoi(argv[i]); 
				Done=1; 
			}
		}
	}
	
	NbBytes=Bits/8*Nb;
	
	memfd = open("/dev/mem", O_RDONLY);
	if (memfd < 0) { fprintf(stderr, "Can't open /dev/mem: %s\n", 
strerror(errno)); return errno; }
	
	mapped_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, memfd, 
Address & ~MAP_MASK);
	if (mapped_base == (void *) -1) { fprintf(stderr, "Can't map 
the memory to user space: %s\n", strerror(errno)); close(memfd); return 
errno; }

	for (Virt=mapped_base+(Address&MAP_MASK), Phy=Address; 
Phy<Address+NbBytes; Virt+=4*4, Phy+=4*4) {
		if (Virt>=mapped_base+MAP_SIZE) { fprintf(stderr, 
"Reached page boundary - Stopped\n"); Ret=1; goto Quit; }
		switch (Bits) {
			case 8:printf("%08x~%08x: %02x %02x 
%02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  
%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
					   Phy, 
Virt,
						
(int)*((unsigned char*)Virt+ 0), (int)*((unsigned char*)Virt+ 1), 
(int)*((unsigned char*)Virt+ 2), (int)*((unsigned char*)Virt+ 3),
						
(int)*((unsigned char*)Virt+ 4), (int)*((unsigned char*)Virt+ 5), 
(int)*((unsigned char*)Virt+ 6), (int)*((unsigned char*)Virt+ 7),
						
(int)*((unsigned char*)Virt+ 8), (int)*((unsigned char*)Virt+ 9), 
(int)*((unsigned char*)Virt+10), (int)*((unsigned char*)Virt+11),
						
(int)*((unsigned char*)Virt+12), (int)*((unsigned char*)Virt+13), 
(int)*((unsigned char*)Virt+14), (int)*((unsigned char*)Virt+15),
						
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
						
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
						
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
						
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
					); break;
			case 16:printf("%08x~%08x: %04x %04x  
%04x %04x  %04x %04x  %04x %04x  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
					   Phy, 
Virt,
						
(int)*((unsigned short*)Virt+0), (int)*((unsigned short*)Virt+1),
						
(int)*((unsigned short*)Virt+2), (int)*((unsigned short*)Virt+3), 
						
(int)*((unsigned short*)Virt+4), (int)*((unsigned short*)Virt+5),
						
(int)*((unsigned short*)Virt+6), (int)*((unsigned short*)Virt+7),
						
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
						
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
						
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
						
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
					); break;
			case 32:printf("%08x~%08x: %08x %08x 
%08x %08x  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
					   Phy, 
Virt,
						
*((unsigned int*)Virt+0),
						
*((unsigned int*)Virt+1),
						
*((unsigned int*)Virt+2),
						
*((unsigned int*)Virt+3),
						
F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
						
F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
						
F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
						
F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
					); break;
		}
	}
		
Quit:
	munmap(mapped_base, NbBytes);
	close(memfd);
	return Ret;
}


Thanks
-- 
Guillaume Dargaud
http://www.gdargaud.net/

[toc] | [next] | [standalone]


#10762

FromNoob <root@127.0.0.1>
Date2011-09-23 16:44 +0200
Message-ID<j5i60u$ftb$1@dont-email.me>
In reply to#10758
Guillaume Dargaud wrote:

> I know it's frowned upon to post system-specific code here, but I'd like to 
> know if the error is in my C code (wrong pointer manipulation), in my 
> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC 
> processor).

IMO, you'll get better answers in comp.unix.programmer

[toc] | [prev] | [next] | [standalone]


#10771

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-09-23 17:16 +0100
Message-ID<0.85cb90bd0f5c4eb344da.20110923173028BST.87obybxluj.fsf@bsb.me.uk>
In reply to#10758
Guillaume Dargaud <use_the_contact_form@www.gdargaud.net> writes:

> I know it's frowned upon to post system-specific code here, but I'd like to 
> know if the error is in my C code (wrong pointer manipulation), in my 
> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC 
> processor).

I'm going to comment mainly on the C matters.  I've no idea about the
rest.

> Basically I get different results when trying to read the memory as a single 
> byte, as a short or as an int (the only one that returns correct
> results).

Are you sure the memory content is not changing?  Maybe you know what is
to be expected there.

<snip>
> // Note: this is strictly 32-bit code with 32-bit pointers
> // Note 2: only root can use this program
>
> #include <ctype.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <iso646.h>
> #include <errno.h>
>
> #include <fcntl.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <sys/mman.h>
>
> #include <linux/types.h>
>
> static char Str[]="%s [-b|s|w] address [nb]\n"
> 	"Physical memory dump (using /dev/mem and mmap)\n"
> 	"-b:   byte dump (default)\n"
> 	"-s:   short dump\n"
> 	"-w:   word dump\n"
> 	"nb:   number of values to dump (default 1 which prints 16 
> bytes, 8 short or 4 words, must be less than 4kb)\n"
> 	"Notes: You can use 0x notation for address and nb. Only root 
> can access /dev/mem.\n";
>
> #define Usage { fprintf(stderr, Str, argv[0]); return 1; }
>
> // Display printable chars as themselves, or replaces non-printable by '.'
> #define F(ch, offset) ( isprint(*((unsigned char*)(ch)+(offset))) ? 
> *((unsigned char*)(ch)+(offset)) : '.' )

In general, a function is preferable to a macro.  I'd write both of
these as functions.

> #define MAP_SIZE 4096UL
> #define MAP_MASK (MAP_SIZE - 1)
>
> int main (int argc, char *argv[]) {
> 	int Bits=8;	// 8, 16 or 32
> 	unsigned int Address=0;
> 	unsigned int Nb=1, NbBytes;

These are set using strtoul so unsigned long seems like a more natural
type.  If you switched to unsigned long long you could probably dispense
with the 32-bit restriction.

> 	int i, Done=0;

C99 (which you seem to be using) has bool type if for flag variables.

> 	unsigned int Phy;
> 	int memfd=0, Ret=0;
> 	void *mapped_base=NULL, *Virt=NULL;

There's an odd mixture of case in your names.  It's not very important
but I can't help trying to work out what the Caps are intended to
convey.  If it's nothing, it's clearer to make the variables all look
the same.

> 	if (sizeof(void*)!=sizeof(int)) {
> 		fprintf(stderr, "This can run only on 32-bit 
> systems with 32-bit pointers\n"); return 1; }

The test does not match the error.  If int were anything but 32 bits,
the test would not do what it claims.  Maybe

  if (CHAR_BIT != 8 || sizeof (void *) != 4)

(The CHAR_BIT test is not really needed since this is POSIX code and
POSIX requires that char has 8 bits.)

> 	if (argc<2 or argc>4) Usage;
> 	
> 	for (i=1; i<argc; i++) {
> 		     if (strcmp(argv[i], "-b")==0) Bits=8;
> 		else if (strcmp(argv[i], "-s")==0) Bits=16;
> 		else if (strcmp(argv[i], "-w")==0) Bits=32;
> 		else if (argv[i][0]!='-') { 
> 			if (Done) {
> 				if (argv[i][0]=='0' and 
> argv[i][1]=='x') Nb=strtoul(argv[i]+2, NULL, 16); 
> 				else Nb=atoi(argv[i]); 

strtoul works for the same strings are atoi, and it understands the 0x
prefix so this test does not buy you very much.

> 			}
> 			else {
> 				if (argv[i][0]=='0' and 
> argv[i][1]=='x') Address=strtoul(argv[i]+2, NULL, 16); 
> 				else 
> Address=atoi(argv[i]); 
> 				Done=1; 

Done is too neutral a name for my taste.  I'd call it address_arg_seen or
some such thing.  I might be tempted to do away with it and use a
pointer to Address which gets switched to point to Nb.  Not sure, but I
might.

> 			}
> 		}
> 	}
> 	
> 	NbBytes=Bits/8*Nb;
> 	
> 	memfd = open("/dev/mem", O_RDONLY);
> 	if (memfd < 0) { fprintf(stderr, "Can't open /dev/mem: %s\n", 
> strerror(errno)); return errno; }
> 	
> 	mapped_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, memfd, 
> Address & ~MAP_MASK);
> 	if (mapped_base == (void *) -1) { fprintf(stderr, "Can't map 
> the memory to user space: %s\n", strerror(errno)); close(memfd); return 
> errno; }
>
> 	for (Virt=mapped_base+(Address&MAP_MASK), Phy=Address; 
> Phy<Address+NbBytes; Virt+=4*4, Phy+=4*4) {

C does not permit arithmetic on void *.  Since you want to access bytes,
I'd make the pointers unsigned char * right form the start.

There's no need for 4*4.  One 4 is by design (you print in blocks of 4)
but the other is sizeof (void *) and that's both more portable and makes
the intent clearer -- move on by 4 pointers.  That won't remove all of
the 32-bitness from the code, but it helps.

> 		if (Virt>=mapped_base+MAP_SIZE) { fprintf(stderr, 
> "Reached page boundary - Stopped\n"); Ret=1; goto Quit; }

Here, the goto is the equivalent of a break.  I think break is clearer.

> 		switch (Bits) {
> 			case 8:printf("%08x~%08x: %02x %02x 
> %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  %02x %02x %02x %02x  
> %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
> 					   Phy, 
> Virt,

You are playing fast a loose with printf formats and types.  Virt is a
pointer and %x is not the right format for that.  If you know you want
something more like an integer, convert it.  The ideal type is uintptr_t
which has its own format defined in inttypes.h (PRIxPTR).

> (int)*((unsigned char*)Virt+ 0), (int)*((unsigned char*)Virt+ 1), 
> (int)*((unsigned char*)Virt+ 2), (int)*((unsigned char*)Virt+ 3),

The int cast is not needed.  unsigned char will promote to int.
However, %x expects an unsigned int so a cast to that tye would not be
pointless (though you will get away without it except on malicious
implementations).  If Virt is to remain a void *, I'd assign a temporary

  const unsigned char *ucp = Virt;

just to be able to write:

  ucp[0], ucp[1], ucp[2]

and so on.
					
> (int)*((unsigned char*)Virt+ 4), (int)*((unsigned char*)Virt+ 5), 
> (int)*((unsigned char*)Virt+ 6), (int)*((unsigned char*)Virt+ 7),
> 						
> (int)*((unsigned char*)Virt+ 8), (int)*((unsigned char*)Virt+ 9), 
> (int)*((unsigned char*)Virt+10), (int)*((unsigned char*)Virt+11),
> 						
> (int)*((unsigned char*)Virt+12), (int)*((unsigned char*)Virt+13), 
> (int)*((unsigned char*)Virt+14), (int)*((unsigned char*)Virt+15),
> 						
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
> 						
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
> 						
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
> 						
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)

This is crying out for a function.  The code is repeated three times.
At the least, I'd factor out the common code:

  printf("%08x~%08"PRIuPTR": ", Phy, (uintptr_t)Virt);
  switch (Bits) {
  }
  printf("%c%c%...", F(Virt, 0), F(Virt, 1),...);

rather than repeating it.

> 					); break;
> 			case 16:printf("%08x~%08x: %04x %04x  
> %04x %04x  %04x %04x  %04x %04x  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
> 					   Phy, 
> Virt,

Again I'd use: const unsigned short *usp = Virt; to be able to write
simpler expressions than those below.
				
> (int)*((unsigned short*)Virt+0), (int)*((unsigned short*)Virt+1),
> 						
> (int)*((unsigned short*)Virt+2), (int)*((unsigned short*)Virt+3), 
> 						
> (int)*((unsigned short*)Virt+4), (int)*((unsigned short*)Virt+5),
> 						
> (int)*((unsigned short*)Virt+6), (int)*((unsigned short*)Virt+7),
> 						
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
> 						
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
> 						
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
> 						
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
> 					); break;
> 			case 32:printf("%08x~%08x: %08x %08x 
> %08x %08x  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", 
> 					   Phy, 
> Virt,
> 						
> *((unsigned int*)Virt+0),
> 						
> *((unsigned int*)Virt+1),
> 						
> *((unsigned int*)Virt+2),
> 						
> *((unsigned int*)Virt+3),
> 						
> F(Virt, 0), F(Virt, 1), F(Virt, 2), F(Virt,3),
> 						
> F(Virt, 4), F(Virt, 5), F(Virt, 6), F(Virt,7),
> 						
> F(Virt, 8), F(Virt, 9), F(Virt,10), F(Virt,11),
> 						
> F(Virt,12), F(Virt,13), F(Virt,14), F(Virt,15)
> 					); break;
> 		}
> 	}
> 		
> Quit:
> 	munmap(mapped_base, NbBytes);
> 	close(memfd);
> 	return Ret;
> }

None of these issues seem likely to explain what you see as wrong but
for that you will have to post somewhere like comp.unix.programmer.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#11076

FromGuillaume Dargaud <use_the_contact_form@www.gdargaud.net>
Date2011-09-29 14:53 +0200
Message-ID<j61po7$1hs$2@ccpntc8.in2p3.fr>
In reply to#10771
Thanks for all the comments, I'll do better next time !
The code was a bit of a patch'n'go because it was test code to look into a 
more complex issue, hence the mix of styles.
I'll fix some of the things you mention, though (like the ++ on void*).

Anyway the magic smoke came out of our system, so there won't be any more 
software issues for a while   C:-|
-- 
Guillaume Dargaud
http://www.gdargaud.net/

[toc] | [prev] | [next] | [standalone]


#10836

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2011-09-23 20:21 -0400
Message-ID<j5j7qd$pr1$1@dont-email.me>
In reply to#10758
On 9/23/2011 9:46 AM, Guillaume Dargaud wrote:
> Hello all,
> I know it's frowned upon to post system-specific code here, but I'd like to
> know if the error is in my C code (wrong pointer manipulation), in my
> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC
> processor).
>[...]
> # ./Peek -w 0x81600001 0x10
> 81600001~48006001: 00000000 00000000 00000000 00000000  ................
> 81600011~48006011: 00000000 00000000 00000000 00000000  ................
> 81600021~48006021: 00000000 00000000 00000000 00000000  ................
> 81600031~48006031: 00000000 00000000 00000000 00000000  ................

     In addition to the comments others have offered, it's quite
possible that your processor is unhappy trying to fetch four-byte
integers from odd addresses.  Different processors will behave
differently in the face of improper alignment; among the behaviors
I've actually seen are

     - The processor traps, and the O/S terminates the program
       (often with "SIGBUS" or something like it).

     - The processor traps, and low-level code simulates the
       invalid operation in software, loading bytes one by one
       and assembling the result for you.  The program works but
       takes a thousand or so times as long as if the access had
       been properly aligned.

     - The processor handles the load-and-assemble part without a
       trap and without software intervention.  The program works
       but takes two to eight times as long as normal.

     - The processor completely ignores the offending low-order
       address bits, so when you fetch an int from 0x81600001 you
       get the four bytes 0x81600000-0x81600003 instead of the
       intended 0x81600001-0x81600004.  Peculiar results ensue.

     This list is not exhaustive of all possible outcomes; it's
just the outcomes I personally have observed.  And it's meant as
a warning that your program is on uncertain ground ...

-- 
Eric Sosman
esosman@ieee-dot-org.invalid

[toc] | [prev] | [next] | [standalone]


#10873

FromNobody <nobody@nowhere.com>
Date2011-09-24 18:26 +0100
Message-ID<pan.2011.09.24.17.26.53.650000@nowhere.com>
In reply to#10836
On Fri, 23 Sep 2011 20:21:31 -0400, Eric Sosman wrote:

>      - The processor completely ignores the offending low-order
>        address bits, so when you fetch an int from 0x81600001 you
>        get the four bytes 0x81600000-0x81600003 instead of the
>        intended 0x81600001-0x81600004.  Peculiar results ensue.

The historical ARM behaviour is similar, but with the result rotated such
that the byte at the specified address is the least significant byte of
the result.

IOW, reads use the top 30 bits to determine the address, and the
bottom 2 bits to determine the rotation. Byte reads mask the resulting
word with 0xFF, word reads don't.

[toc] | [prev] | [next] | [standalone]


#11075

FromGuillaume Dargaud <use_the_contact_form@www.gdargaud.net>
Date2011-09-29 14:50 +0200
Message-ID<j61piu$1hs$1@ccpntc8.in2p3.fr>
In reply to#10873
I did some tests removing the Linux specific code, and addressing Ptr, 
Ptr+1, Ptr+4, etc, works as expected (no alignment strangeness).
So It must be some weird Linux virtual memory stuff. not relevant to the 
discussion here.
-- 
Guillaume Dargaud
http://www.gdargaud.net/

[toc] | [prev] | [next] | [standalone]


#11089

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-09-29 21:57 +0000
Message-ID<slrnj89qet.1bk.grahn+nntp@frailea.sa.invalid>
In reply to#10836
On Sat, 2011-09-24, Eric Sosman wrote:
> On 9/23/2011 9:46 AM, Guillaume Dargaud wrote:
>> Hello all,
>> I know it's frowned upon to post system-specific code here, but I'd like to
>> know if the error is in my C code (wrong pointer manipulation), in my
>> handling of Linux virtual mem or in weird CPU mem alignments (it's a PPC
>> processor).

Speaking as a C programmer, whatever PPC may do isn't weird.  If your
code breaks on PPC, it's because it's broken from a language standpoint.

>> # ./Peek -w 0x81600001 0x10
>> 81600001~48006001: 00000000 00000000 00000000 00000000  ................
>> 81600011~48006011: 00000000 00000000 00000000 00000000  ................
>> 81600021~48006021: 00000000 00000000 00000000 00000000  ................
>> 81600031~48006031: 00000000 00000000 00000000 00000000  ................
>
>      In addition to the comments others have offered, it's quite
> possible that your processor is unhappy trying to fetch four-byte
> integers from odd addresses.

> Different processors will behave
> differently in the face of improper alignment; among the behaviors
> I've actually seen are
...

>      - The processor handles the load-and-assemble part without a
>        trap and without software intervention.  The program works
>        but takes two to eight times as long as normal.

I'm pretty sure PPC belongs to the "minor slowdown" category. I write
PPC code for a living, and treat casts which may cause misalignment as
minor bugs, worth fixing if I'm rewriting that part anyway for other
reasons.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web