1 // Copyright 2012 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // This source file provides replacements for libc functions that we need. If
30 // we call the libc functions directly we risk crashing in the dynamic linker
31 // as it tries to resolve uncached PLT entries.
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h> // Must come first
35 #endif
36
37 #include "common/linux/linux_libc_support.h"
38
39 #include <stddef.h>
40
41 extern "C" {
42
my_strlen(const char * s)43 size_t my_strlen(const char* s) {
44 size_t len = 0;
45 while (*s++) len++;
46 return len;
47 }
48
my_strcmp(const char * a,const char * b)49 int my_strcmp(const char* a, const char* b) {
50 for (;;) {
51 if (*a < *b)
52 return -1;
53 else if (*a > *b)
54 return 1;
55 else if (*a == 0)
56 return 0;
57 a++;
58 b++;
59 }
60 }
61
my_strncmp(const char * a,const char * b,size_t len)62 int my_strncmp(const char* a, const char* b, size_t len) {
63 for (size_t i = 0; i < len; ++i) {
64 if (*a < *b)
65 return -1;
66 else if (*a > *b)
67 return 1;
68 else if (*a == 0)
69 return 0;
70 a++;
71 b++;
72 }
73
74 return 0;
75 }
76
77 // Parse a non-negative integer.
78 // result: (output) the resulting non-negative integer
79 // s: a NUL terminated string
80 // Return true iff successful.
my_strtoui(int * result,const char * s)81 bool my_strtoui(int* result, const char* s) {
82 if (*s == 0)
83 return false;
84 int r = 0;
85 for (;; s++) {
86 if (*s == 0)
87 break;
88 const int old_r = r;
89 r *= 10;
90 if (*s < '0' || *s > '9')
91 return false;
92 r += *s - '0';
93 if (r < old_r)
94 return false;
95 }
96
97 *result = r;
98 return true;
99 }
100
101 // Return the length of the given unsigned integer when expressed in base 10.
my_uint_len(uintmax_t i)102 unsigned my_uint_len(uintmax_t i) {
103 if (!i)
104 return 1;
105
106 int len = 0;
107 while (i) {
108 len++;
109 i /= 10;
110 }
111
112 return len;
113 }
114
115 // Convert an unsigned integer to a string
116 // output: (output) the resulting string is written here. This buffer must be
117 // large enough to hold the resulting string. Call |my_uint_len| to get the
118 // required length.
119 // i: the unsigned integer to serialise.
120 // i_len: the length of the integer in base 10 (see |my_uint_len|).
my_uitos(char * output,uintmax_t i,unsigned i_len)121 void my_uitos(char* output, uintmax_t i, unsigned i_len) {
122 for (unsigned index = i_len; index; --index, i /= 10)
123 output[index - 1] = '0' + (i % 10);
124 }
125
my_strchr(const char * haystack,char needle)126 const char* my_strchr(const char* haystack, char needle) {
127 while (*haystack && *haystack != needle)
128 haystack++;
129 if (*haystack == needle)
130 return haystack;
131 return (const char*) 0;
132 }
133
my_strrchr(const char * haystack,char needle)134 const char* my_strrchr(const char* haystack, char needle) {
135 const char* ret = NULL;
136 while (*haystack) {
137 if (*haystack == needle)
138 ret = haystack;
139 haystack++;
140 }
141 return ret;
142 }
143
my_memchr(const void * src,int needle,size_t src_len)144 void* my_memchr(const void* src, int needle, size_t src_len) {
145 const unsigned char* p = (const unsigned char*)src;
146 const unsigned char* p_end = p + src_len;
147 for (; p < p_end; ++p) {
148 if (*p == needle)
149 return (void*)p;
150 }
151 return NULL;
152 }
153
154 // Read a hex value
155 // result: (output) the resulting value
156 // s: a string
157 // Returns a pointer to the first invalid charactor.
my_read_hex_ptr(uintptr_t * result,const char * s)158 const char* my_read_hex_ptr(uintptr_t* result, const char* s) {
159 uintptr_t r = 0;
160
161 for (;; ++s) {
162 if (*s >= '0' && *s <= '9') {
163 r <<= 4;
164 r += *s - '0';
165 } else if (*s >= 'a' && *s <= 'f') {
166 r <<= 4;
167 r += (*s - 'a') + 10;
168 } else if (*s >= 'A' && *s <= 'F') {
169 r <<= 4;
170 r += (*s - 'A') + 10;
171 } else {
172 break;
173 }
174 }
175
176 *result = r;
177 return s;
178 }
179
my_read_decimal_ptr(uintptr_t * result,const char * s)180 const char* my_read_decimal_ptr(uintptr_t* result, const char* s) {
181 uintptr_t r = 0;
182
183 for (;; ++s) {
184 if (*s >= '0' && *s <= '9') {
185 r *= 10;
186 r += *s - '0';
187 } else {
188 break;
189 }
190 }
191 *result = r;
192 return s;
193 }
194
my_memset(void * ip,char c,size_t len)195 void my_memset(void* ip, char c, size_t len) {
196 char* p = (char*) ip;
197 while (len--)
198 *p++ = c;
199 }
200
my_strlcpy(char * s1,const char * s2,size_t len)201 size_t my_strlcpy(char* s1, const char* s2, size_t len) {
202 size_t pos1 = 0;
203 size_t pos2 = 0;
204
205 while (s2[pos2] != '\0') {
206 if (pos1 + 1 < len) {
207 s1[pos1] = s2[pos2];
208 pos1++;
209 }
210 pos2++;
211 }
212 if (len > 0)
213 s1[pos1] = '\0';
214
215 return pos2;
216 }
217
my_strlcat(char * s1,const char * s2,size_t len)218 size_t my_strlcat(char* s1, const char* s2, size_t len) {
219 size_t pos1 = 0;
220
221 while (pos1 < len && s1[pos1] != '\0')
222 pos1++;
223
224 if (pos1 == len)
225 return pos1;
226
227 return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1);
228 }
229
my_isspace(int ch)230 int my_isspace(int ch) {
231 // Matches the C locale.
232 const char spaces[] = " \t\f\n\r\t\v";
233 for (size_t i = 0; i < sizeof(spaces); i++) {
234 if (ch == spaces[i])
235 return 1;
236 }
237 return 0;
238 }
239
240 } // extern "C"
241