On 7/4/21 8:38 PM, Thomas Huth wrote:
> On 04/07/2021 19.07, Philippe Mathieu-Daudé wrote:
>> Linking on Haiku OS fails:
>>
>>   
>> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld:
>>
>>    error:
>> libqemu-mips-softmmu.fa.p/target_mips_tcg_sysemu_mips-semi.c.o(.rodata) is
>> too large (0xffff405a bytes)
>>   
>> /boot/system/develop/tools/bin/../lib/gcc/x86_64-unknown-haiku/8.3.0/../../../../x86_64-unknown-haiku/bin/ld:
>>
>>    final link failed: memory exhausted
>>    collect2: error: ld returned 1 exit status
>>
>> This is because the host_to_mips_errno[] uses errno as index,
>> for example:
>>
>>    static const uint16_t host_to_mips_errno[] = {
>>        [ENAMETOOLONG] = 91,
>>        ...
>>
>> and Haiku defines [*] ENAMETOOLONG as:
>>
>>     12 /* Error baselines */
>>     13 #define B_GENERAL_ERROR_BASE              INT_MIN
>>     ..
>>     22 #define B_STORAGE_ERROR_BASE              (B_GENERAL_ERROR_BASE
>> + 0x6000)
>>    ...
>>    106 #define B_NAME_TOO_LONG                   (B_STORAGE_ERROR_BASE
>> + 4)
>>    ...
>>    211 #define ENAMETOOLONG                     
>> B_TO_POSIX_ERROR(B_NAME_TOO_LONG)
>>
>> so the array ends up beeing indeed too big.
>>
>> Since POSIX errno can't be use as indexes on Haiku,
>> rewrite errno_mips() using a GHashTable.
>>
>> [*]
>> https://github.com/haiku/haiku/blob/r1beta3/headers/os/support/Errors.h#L130
>>
>>
>> Signed-off-by: Philippe Mathieu-Daudé <f4...@amsat.org>
>> ---
>>   target/mips/tcg/sysemu/mips-semi.c | 62 ++++++++++++++++++++++--------
>>   1 file changed, 45 insertions(+), 17 deletions(-)

>> +static void uhi_errno_init(void)
>> +{
>> +    gboolean ret = TRUE;
>> +
>> +    uhi_errno_hash_table = g_hash_table_new(NULL, NULL);
>> +
>> +    /*
>> +     * Unified Hosting Interface (rev 1.1.6)
>> +     * Appendix A. "Error values"
>> +     */
>> +    uhi_errno_insert(ENAMETOOLONG,  91);
>>   #ifdef ELOOP
>> -    [ELOOP]        = 92,
>> +    uhi_errno_insert(ELOOP,         92);
>>   #endif
>> -};
>> +#ifdef EOVERFLOW
>> +    uhi_errno_insert(EOVERFLOW,     139);
>> +#endif
>> +    assert(ret == TRUE);
>> +}
>>     static int errno_mips(int host_errno)
>>   {
>> -    if (host_errno < 0 || host_errno >=
>> ARRAY_SIZE(host_to_mips_errno)) {
>> -        return EINVAL;
>> -    } else if (host_to_mips_errno[host_errno]) {
>> -        return host_to_mips_errno[host_errno];
>> -    } else {
>> -        return host_errno;
>> +    gpointer uhi_errno;
>> +
>> +    if (uhi_errno_hash_table == NULL) {
>> +        uhi_errno_init();
>>       }
>> +
>> +    if (host_errno == 0) {
>> +        return 0;
>> +    }
>> +    if (g_hash_table_lookup_extended(uhi_errno_hash_table,
>> +                                     GINT_TO_POINTER(host_errno),
>> +                                     NULL, &uhi_errno)) {
>> +        return GPOINTER_TO_INT(uhi_errno);
>> +    }
>> +    return EINVAL; /* Not reachable per the specification */
>>   }
> 
> Why not simply use a switch-case statement instead? ... that's simpler
> and still allows to compiler to optimize if the errno values are in a
> compact range.

I was expecting the #ifdef'ry to be ugly, but there isn't that many
actually. Sigh :(

Reply via email to