Fork us on GitHub Follow us on Facebook Follow us on Twitter

Opened 3 years ago

Closed 3 years ago

#658 closed defect (fixed)

Dynamically linked build hangs on async_futex

Reported by: Jakub Jermář Owned by: Jakub Jermář
Priority: major Milestone: 0.7.0
Component: helenos/lib/c Version: mainline
Keywords: Cc:
Blocker for: Depends on:
See also:

Description

As of mainline,2440, the dynamically-linked ia32 build hangs on async_futex, which is zero on __entry (the expected value is 1).

Not sure if this is relevant, but async_futex is defined both in the dynamically linked program's, such as klog, .bss section (excerpt from klog.map):

.bss            0x0000000000002ce0       0x60
 *(.dynbss)
 .dynbss        0x0000000000002ce0        0xc /home/jermar/software/HelenOS.mainline/uspace/lib/c/arch/ia32/src/entry.o
                0x0000000000002ce0                __syscall_fast_func
                0x0000000000002ce4                async_futex
                0x0000000000002ce8                stderr

and the .data section of the dynamically linked libc.so.0 (excerpt from libc.so.0.0.map):

.data          0x000000000003bb9c        0x4 libc.la(async.lo)
                0x000000000003bb9c                async_futex

Attachments (1)

r_i386_copy.patch (5.0 KB) - added by Jakub Jermář 3 years ago.
Suggested fix

Download all attachments as: .zip

Change History (6)

comment:1 Changed 3 years ago by Jakub Jermář

Okay, I think that it is okay for a symbol to be defined both in the shared library and the dynamic program. For these cases, a special relocation type R_I386_COPY is used. See for example this link for a more detailed description.

HelenOS rtld indeed seems to be processing 3 relocations of this type for the program. However, the problem seems to be that the source and destination address in the following memcpy() are the same, so the copy does not really happen and the async_futex variable remains uninitialized:

		case R_386_COPY:
			/*
			 * Copy symbol data from shared object to specified
			 * location.
			 */
			DPRINTF("fixup R_386_COPY (s)\n");
			sym_size = sym->st_size;
			if (sym_size != sym_def->st_size) {
				printf("Warning: Mismatched symbol sizes.\n");
				/* Take the lower value. */
				if (sym_size > sym_def->st_size)
					sym_size = sym_def->st_size;
			}
			memcpy(r_ptr, (const void *)sym_addr, sym_size);
			break;

This code snippet comes from mainline/uspace/lib/c/arch/ia32/src/rtld/reloc.c#L149. r_ptr is the same as sym_addr and both come from the program.

comment:2 Changed 3 years ago by Jiri Svoboda

Thanks for the reference, which clearly explains the problem.

The destination r_ptr is the address of the symbol in the executable and the source address is determined using symbol_def_find(). Because the symbol is defined in the executable and the executable is searched first, symbol_def_find() returns the symbol in the executable.

Clearly for R_386_COPY we search for the definition in the wrong place. It seems we need to look for the definition everywhere except for the executable. Now the question is, whether this is true just for the COPY relocation, or whether we should do the same for all relocations.

comment:3 Changed 3 years ago by Jakub Jermář

Thanks for confirming this. In the meantime, I've put together a patch which fixes this for me, please have a look at it if it looks reasonable. As for whether this needs to be done for all or only this relocation type, it seems to me that R_*_COPY is exceptional in that it involves a source and a destination. I don't know if there are other relocation types with a similar property. Otherwise there will be only relocation types where source and destination are the same thing. Btw, do you know how it is arranged that all the references from all modules to these variables will go only to the copies?

Changed 3 years ago by Jakub Jermář

Attachment: r_i386_copy.patch added

Suggested fix

comment:4 Changed 3 years ago by Jiri Svoboda

I think you've answered my question (and your question). If all references except R_*_COPY use the 'standard' search strategy, starting at the root/executable, they will find the definition in the executable and reference it.

Thanks for the patch, it looks good on a functional level. I will fix it in a very similar way, but with some cosmetic changes.

comment:5 Changed 3 years ago by Jakub Jermář

Resolution: fixed
Status: newclosed

Fixed in mainline,2454.

Note: See TracTickets for help on using tickets.