ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Do you mean, the new value of 32-63 bits will have by default high as binary value 1 so it becomes 0x ff ff ff ff <0-31 old value> ?
No.
If the old value was 0x0000000 through 0x7FFFFFFF the new value will be 0x00000000<0-31 old value> but if the old value was 0x80000000 through 0xFFFFFFFF the new value will be 0xFFFFFFFF<0-31 old value>
When I used the word "high" in my previous attempt to explain, I meant high bit positions within the 32 or 64 bit integer, not the high bit value (1).
What they're talking about is sign extending. (Maybe that's not the correct term but I think you get what I mean.)
If the quantity that you are dealing with is assumed to be a 32-bit signed quantity, then the most-significant bit (MSB) is a sign-bit and the number is in so-called two's complement notation. The quantity "-1" is $FFFFFFFF, in the customary hexadecimal.
If you load this 32-bit signed quantity into a 64-bit accumulator, the leftmost bit (the sign-bit) is extended into all of the unoccupied slots, since the 64-bit version of "-1" is of course $FFFFFFFFFFFFFFFF, thus correctly preserving its two's-complement representation.
Now, what if you, the almighty programmer, assert that the value is, in fact, unsigned? (Obviously, it's impossible to tell one from the other by looking at the bits...) In this case, $FFFFFFFF is the decimal quantity 4,294,967,296 and the proper way to load it into a 64-bit register produces $00000000FFFFFFFF.
Certainly, one of the "gotchas" of 64-bithood is that int is signed, and that it is also carelessly used as being "synonymous with a pointer," which in this case is no longer true. If you assumed a 32-bit world, then you could simply handle these quantities with impunity ... just ignore the MSB when you wanted to. But, now, sign-extending is occurring rather constantly if the word-size of the data you're dealing with is still 32-bits but now your CPU speaks 64. Suddenly, all of the leftmost-bits of your derived address (as many as your hardware actually cares about ...) have transmogrified themselves into 1's, and you are not looking anywhere near the right place in memory anymore. C'est la guerre...
Last edited by sundialsvcs; 02-10-2012 at 08:32 AM.
I was going through this thread and I thought my problem/question is similar to this one..
Doesn't look similar to me. I think sundialsvcs answered on the original topic, so that doesn't help you. That's one of the risks of reopening an old thread for a new question.
It would be helpful to know the declaration of the function that was compiled/loaded as func_instance@plt
Based on the subsequent code, I expect that function was declared as returning a pointer to some struct type but when called, it returned a zero (NULL pointer). In x86_64 pointers are returned from functions in %rax
That takes the character 79 beyond what is pointed to by %rax and moves it into %al (which is the low byte of %rax) and clears the remainder of %rax.
But you are reporting that it instead causes a NULL pointer dereference, so I assume %rax had zero in it before executing that instruction.
Quote:
Platform is an ia64
No. It is x86_64. IA64 is a different Intel 64 bit architecture.
Quote:
elaborate a little more on these instructions.
Code:
jo 0x7ffff3e98f0f <func_instance+351>
Garbage (incorrect disassembly) caused by starting to disassemble at an address that wasn't an instruction boundary.
Code:
mov 0x10(%rsp),%rdi
Move a 64 bit quantity, probably from a local variable, into the register used to pass the first parameter to a function.
Code:
callq 0x7ffff3e1a1f8 <func_instance@plt>
Call a function, I think in a .so rather than in the current binary.
Code:
mov 0x8(%rsp),%rdx
Move a 64 bit quantity, probably from a local variable, into %rdx. Later code indicates that 64 bit quantity is a pointer.
Code:
mov %rax,%rsi
Make a copy (in %rsi) of the pointer returned by the previous function call.
Code:
movzbl 0x4f(%rax),%eax
cmp 0x4f(%rdx),%al
je 0x7ffff3e98fa0 <func_instance+496>
That is what an if statement compiles to. The original if would have been something equivalent to if ( x->f != y->f )
where x is the struc pointer loaded earlier into %rdx from a local variable and y is the struct pointer returned by the function call and f is the char at offset 79 in the struct.
You are correct, thank you ... I replied on the original.
There are several reasons why such code can "fall down," and one of the very common reasons are differences in the so-called subroutine calling conventions that are being used. How does the caller supply arguments to the callee? This usually crops up when the code being called was compiled at a different time and perhaps by a different compiler, e.g. the target code is in a library of some kind. But, if the calls work anywhere in the application, this cannot be the problem.
Most of the time, if you find yourself diving down into assembly-language instructions, you are chasing a pointless red herring. The assembly code, whatever it may be, may be presumed to be "correct." The root cause of the problem must be chased down and understood, and it will inevitably be somewhere in your code but it probably is not terribly close to the point where the application fell off its log footbridge and landed face-down in the mud of the debugger.
I can count on the fingers of one hand the number of times when I successfully used a low-level debugger to usefully solve anything in application programming.
Most of the time, if you find yourself diving down into assembly-language instructions, you are chasing a pointless red herring.
In the current case, whatever bug caused that function to return a null pointer or whatever bug caused the calling code to not tolerate the return of a null pointer should have been easy to identify at the source level without diving into asm.
But...
Quote:
I can count on the fingers of one hand the number of times when I successfully used a low-level debugger to usefully solve anything in application programming.
I get called into each of the situations of impossible to debug by ordinary means that crop up in a moderate size group of programmers working on two extremely large complicated products. If it is difficult enough to call for my help at all, it is usually difficult enough to require looking at the asm code.
So I can count on the fingers of one hand the number of times this year (2012) that I successfully used asm level debugging to solve a problem in application programming that couldn't be solved otherwise. But it is still fairly early in the year. Longer term, it seems to happen less than once a week, but not a lot less.
Doesn't look similar to me. I think sundialsvcs answered on the original topic, so that doesn't help you. That's one of the risks of reopening an old thread for a new question.
It would be helpful to know the declaration of the function that was compiled/loaded as func_instance@plt
Based on the subsequent code, I expect that function was declared as returning a pointer to some struct type but when called, it returned a zero (NULL pointer). In x86_64 pointers are returned from functions in %rax
That takes the character 79 beyond what is pointed to by %rax and moves it into %al (which is the low byte of %rax) and clears the remainder of %rax.
But you are reporting that it instead causes a NULL pointer dereference, so I assume %rax had zero in it before executing that instruction.
No. It is x86_64. IA64 is a different Intel 64 bit architecture.
Code:
jo 0x7ffff3e98f0f <func_instance+351>
Garbage (incorrect disassembly) caused by starting to disassemble at an address that wasn't an instruction boundary.
Code:
mov 0x10(%rsp),%rdi
Move a 64 bit quantity, probably from a local variable, into the register used to pass the first parameter to a function.
Code:
callq 0x7ffff3e1a1f8 <func_instance@plt>
Call a function, I think in a .so rather than in the current binary.
Code:
mov 0x8(%rsp),%rdx
Move a 64 bit quantity, probably from a local variable, into %rdx. Later code indicates that 64 bit quantity is a pointer.
Code:
mov %rax,%rsi
Make a copy (in %rsi) of the pointer returned by the previous function call.
Code:
movzbl 0x4f(%rax),%eax
cmp 0x4f(%rdx),%al
je 0x7ffff3e98fa0 <func_instance+496>
That is what an if statement compiles to. The original if would have been something equivalent to if ( x->f != y->f )
where x is the struc pointer loaded earlier into %rdx from a local variable and y is the struct pointer returned by the function call and f is the char at offset 79 in the struct.
Thank you both of you for your valued suggestion. I am sorry for posting it here though.
yes rax had zero in it before executing the instruction;
Code:
movzbl 0x4f(%rax),%eax
Because when I executed;
[p/x $rax & p/x $rsi]
both of them returned 0.
basically the function called in callq has returned a NULL.
I shall paste the function code tomorrow and the formal parameter being passed to the function is an unsigned int(once i post the func, may be it will be clearer). Again, thank you for your brilliant thoughts.
I shall paste the function code tomorrow and the formal parameter being passed to the function is an unsigned int
1) do you understand the difference between a "formal parameter" and an "actual parameter"?
2) If it is an unsigned int, why is it passed by copying a 64 bit local variable into a 64 bit register?
If the actual parameter were 64 bit and the formal parameter were unsigned int and the function were properly declared for the calling module, I think the compiler would have chosen a more efficient instruction to pass the parameter (but I'm not certain of that and the less efficient instruction should not be functionally incorrect).
The parameter passed to the function in callq is a const unsigned int. The function being called is the overloaded subscript operator
if (*(myRow[myCol[*loc].a]) == item)
"a" is a member of a structure. Looking at asm code, myCol[*loc].a is null(UINT_MAX). By dereferencing it with myRow it hit the SIGSEGV!
myCol[*loc].a should have had a valid value, it should not have returned UINT_MAX
typedef struct
{
unsigned char a;
}user;
user *myCol;
Last edited by akshay_satish; 02-13-2012 at 06:55 AM.
I can't connect the small snips of C++ code in your post #24 to the small chunk of asm code in your post #17.
If you are correct about passing unsigned int, I guess the %rdi could be incorrect disassembly in post #17. If you started the disassembly a few instructions earlier, so misalignment problems are resolved before reaching the previous instruction, we could be sure.
You seem to be saying the function with the run time name func_instance@plt is an overloaded subscript operator returning a reference. Is that what you mean? If I understand you correctly, it is computing a reference to myCol[*loc] and that reference is an invalid pointer.
But I don't follow what you are saying about UINT_MAX and especially not what you are saying about myCol[*loc].a. That is a character. You seem to be saying its value is invalid, but if that is related to the asm code you posted, it is the address myCol[*loc] that is invalid, not the value myCol[*loc].a.
I can't connect the small snips of C++ code in your post #24 to the small chunk of asm code in your post #17.
If you are correct about passing unsigned int, I guess the %rdi could be incorrect disassembly in post #17. If you started the disassembly a few instructions earlier, so misalignment problems are resolved before reaching the previous instruction, we could be sure.
You seem to be saying the function with the run time name func_instance@plt is an overloaded subscript operator returning a reference. Is that what you mean? If I understand you correctly, it is computing a reference to myCol[*loc] and that reference is an invalid pointer.
But I don't follow what you are saying about UINT_MAX and especially not what you are saying about myCol[*loc].a. That is a character. You seem to be saying its value is invalid, but if that is related to the asm code you posted, it is the address myCol[*loc] that is invalid, not the value myCol[*loc].a.
I am so SORRY. a is not a char!
typedef struct
{
unsigned int a;
}user;
the overloaded [] operator, it basically returns pointer to object stored at the index passed as a parameter.
So what i was trying to say was;
myCol[*loc].a was NULL when dereferenced caused the SEGV.
That makes it even harder to see a connection with the disassembly you posted before.
I think the disassembly you posted before is a different if statement than the one you are looking at now.
I assume the disassembly correctly represents the point of the seg fault, so I think you are looking in the wrong place in the source code for that seg fault.
How big is func_instance ? If you post the whole source code to func_instance, I might be able to estimate the correct point of the seq fault.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.