1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
Emulation of some arm programs fail with "Assertion `have_guest_base' failed."
This issue is observer with QEMU ToT, checked out around May 15th (but I believe it is present in current master too), and wasn't present in QEMU v5.0.0.
I am using 32-bit Intel(R) Pentium(R) M processor 1.73GHz host.
Arm cross-compiler is a standard cross-compiler that comes with Debian-based distributions, and gcc version is:
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Debian 8.3.0-2) 8.3.0
Compile this program with cross compiler:
$ arm-linux-gnueabi-gcc -O2 -static toupper_string.c -o toupper_string-arm
Emulation with QEMU v5.0.0 is correct, and gives expected output:
$ ~/Build/qemu-5.0.0/build-gcc/arm-linux-user/qemu-arm ./toupper_string-arm
CONTROL RESULT: (toupper_string)
nwlrbbmqbhcdarz owkkyhiddqscdxr jmowfrxsjybldbe fsarcbynecdyggx xpklorellnmpapq
NWLRBBMQBHCDARZ OWKKYHIDDQSCDXR JMOWFRXSJYBLDBE FSARCBYNECDYGGX XPKLORELLNMPAPQ
While, in case of QEMU master it fails:
$ ~/Build/qemu-master/build-gcc/arm-linux-user/qemu-arm ./toupper_string-arm
qemu-arm: /home/rtrk/Build/qemu-master/linux-user/elfload.c:2294: probe_guest_base: Assertion `have_guest_base' failed.
Aborted
There are many other programs that exibit the same behavior. The failure is arm-sprecific.
-----------------------------------------------------
source code: (let's call this file toupper_string.c) (similar file is also in attachment)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define MAX_STRING_LENGHT 15
#define NUMBER_OF_RANDOM_STRINGS 100
#define DEFAULT_NUMBER_OF_REPETITIONS 30000
#define MAX_NUMBER_OF_REPETITIONS 1000000000
#define NUMBER_OF_CONTROL_PRINT_ITEMS 5
/* Structure for keeping an array of strings */
struct StringStruct {
char chars[MAX_STRING_LENGHT + 1];
};
/**
* Sets characters of the given string to random small letters a-z.
* @param s String to get random characters.
* @len Length of the input string.
*/
static void gen_random_string(char *chars, const int len)
{
static const char letters[] = "abcdefghijklmnopqrstuvwxyz";
for (size_t i = 0; i < len; i++) {
chars[i] = letters[rand() % (sizeof(letters) - 1)];
}
chars[len] = 0;
}
void main (int argc, char* argv[])
{
struct StringStruct random_strings[NUMBER_OF_RANDOM_STRINGS];
struct StringStruct strings_to_be_uppercased[NUMBER_OF_RANDOM_STRINGS];
int32_t number_of_repetitions = DEFAULT_NUMBER_OF_REPETITIONS;
int32_t option;
/* Parse command line options */
while ((option = getopt(argc, argv, "n:")) != -1) {
if (option == 'n') {
int32_t user_number_of_repetitions = atoi(optarg);
/* Check if the value is a negative number */
if (user_number_of_repetitions < 1) {
fprintf(stderr, "Error ... Value for option '-n' cannot be a "
"negative number.\n");
exit(EXIT_FAILURE);
}
/* Check if the value is a string or zero */
if (user_number_of_repetitions == 0) {
fprintf(stderr, "Error ... Invalid value for option '-n'.\n");
exit(EXIT_FAILURE);
}
/* Check if the value is too large */
if (user_number_of_repetitions > MAX_NUMBER_OF_REPETITIONS) {
fprintf(stderr, "Error ... Value for option '-n' cannot be "
"more than %d.\n", MAX_NUMBER_OF_REPETITIONS);
exit(EXIT_FAILURE);
}
number_of_repetitions = user_number_of_repetitions;
} else {
exit(EXIT_FAILURE);
}
}
/* Create an array of strings with random content */
srand(1);
for (size_t i = 0; i < NUMBER_OF_RANDOM_STRINGS; i++) {
gen_random_string(random_strings[i].chars, MAX_STRING_LENGHT);
}
/* Perform uppercasing of a set of random strings multiple times */
for (size_t j = 0; j < number_of_repetitions; j++) {
/* Copy initial set of random strings to the set to be uppercased */
memcpy(strings_to_be_uppercased, random_strings,
NUMBER_OF_RANDOM_STRINGS * (MAX_STRING_LENGHT + 1));
/* Do actual changing case to uppercase */
for (size_t i = 0; i < NUMBER_OF_RANDOM_STRINGS; i++) {
int k = 0;
while (strings_to_be_uppercased[i].chars[k]) {
char ch = strings_to_be_uppercased[i].chars[k] - 32;
memcpy((void *)strings_to_be_uppercased[i].chars + k,
&ch, 1);
k++;
}
}
}
/* Control printing */
printf("CONTROL RESULT: (toupper_string)\n");
for (size_t i = 0; i < NUMBER_OF_CONTROL_PRINT_ITEMS; i++) {
printf(" %s", random_strings[i].chars);
}
printf("\n");
for (size_t i = 0; i < NUMBER_OF_CONTROL_PRINT_ITEMS; i++) {
printf(" %s", strings_to_be_uppercased[i].chars);
}
printf("\n");
}
|