aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordigit@chromium.org <digit@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-08-03 15:01:52 +0000
committerdigit@chromium.org <digit@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2012-08-03 15:01:52 +0000
commite0555f5bdf389f667ebae19f07e7b3d338fca20b (patch)
tree865cea9365f6ddcb8b0720ad365155bf5661f449 /src
parentRemove some linux libc calls from client library. (diff)
downloadbreakpad-e0555f5bdf389f667ebae19f07e7b3d338fca20b.tar.xz
SORRY. It seems I've screwed up my commit for http://breakpad.appspot.com/411002/, since revision 1001 only contains the new src/client/linux/linux_libc_support.cc and none of the other required files.
I'm not sure what happened, but I'm re-uploading the patch has another issue. Review URL: https://breakpad.appspot.com/426002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1002 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src')
-rw-r--r--src/client/linux/minidump_writer/directory_reader.h3
-rw-r--r--src/client/linux/minidump_writer/line_reader.h3
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc16
-rw-r--r--src/client/linux/minidump_writer/linux_ptrace_dumper.cc16
-rw-r--r--src/client/linux/minidump_writer/minidump_writer.cc92
-rw-r--r--src/common/linux/linux_libc_support.h141
-rw-r--r--src/common/linux/linux_libc_support_unittest.cc38
7 files changed, 134 insertions, 175 deletions
diff --git a/src/client/linux/minidump_writer/directory_reader.h b/src/client/linux/minidump_writer/directory_reader.h
index 13365373..a4bde180 100644
--- a/src/client/linux/minidump_writer/directory_reader.h
+++ b/src/client/linux/minidump_writer/directory_reader.h
@@ -37,6 +37,7 @@
#include <errno.h>
#include <string.h>
+#include "common/linux/linux_libc_support.h"
#include "third_party/lss/linux_syscall_support.h"
namespace google_breakpad {
@@ -90,7 +91,7 @@ class DirectoryReader {
reinterpret_cast<kernel_dirent*>(buf_);
buf_used_ -= dent->d_reclen;
- memmove(buf_, buf_ + dent->d_reclen, buf_used_);
+ my_memmove(buf_, buf_ + dent->d_reclen, buf_used_);
}
private:
diff --git a/src/client/linux/minidump_writer/line_reader.h b/src/client/linux/minidump_writer/line_reader.h
index 2d19c66d..779cfeb6 100644
--- a/src/client/linux/minidump_writer/line_reader.h
+++ b/src/client/linux/minidump_writer/line_reader.h
@@ -34,6 +34,7 @@
#include <assert.h>
#include <string.h>
+#include "common/linux/linux_libc_support.h"
#include "third_party/lss/linux_syscall_support.h"
namespace google_breakpad {
@@ -114,7 +115,7 @@ class LineReader {
assert(buf_used_ >= len + 1);
buf_used_ -= len + 1;
- memmove(buf_, buf_ + len + 1, buf_used_);
+ my_memmove(buf_, buf_ + len + 1, buf_used_);
}
private:
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index e9d211ec..6e2bbc8b 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -113,7 +113,7 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
assert(filename_len < NAME_MAX);
if (filename_len >= NAME_MAX)
return false;
- memcpy(filename, mapping.name, filename_len);
+ my_memcpy(filename, mapping.name, filename_len);
filename[filename_len] = '\0';
bool filename_modified = HandleDeletedFileInMapping(filename);
@@ -151,11 +151,11 @@ LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(pid_t pid) const {
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
one_aux_entry.a_type != AT_NULL) {
if (one_aux_entry.a_type == AT_SYSINFO_EHDR) {
- close(fd);
+ sys_close(fd);
return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
}
}
- close(fd);
+ sys_close(fd);
return NULL;
}
@@ -177,11 +177,11 @@ LinuxDumper::FindEntryPoint(pid_t pid) const {
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
one_aux_entry.a_type != AT_NULL) {
if (one_aux_entry.a_type == AT_ENTRY) {
- close(fd);
+ sys_close(fd);
return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
}
}
- close(fd);
+ sys_close(fd);
return NULL;
}
@@ -240,14 +240,14 @@ bool LinuxDumper::EnumerateMappings() {
}
}
MappingInfo* const module = new(allocator_) MappingInfo;
- memset(module, 0, sizeof(MappingInfo));
+ my_memset(module, 0, sizeof(MappingInfo));
module->start_addr = start_addr;
module->size = end_addr - start_addr;
module->offset = offset;
if (name != NULL) {
const unsigned l = my_strlen(name);
if (l < sizeof(module->name))
- memcpy(module->name, name, l);
+ my_memcpy(module->name, name, l);
}
// If this is the entry-point mapping, and it's not already the
// first one, then we need to make it be first. This is because
@@ -351,7 +351,7 @@ bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
return false;
}
- memcpy(path, exe_link, NAME_MAX);
+ my_memcpy(path, exe_link, NAME_MAX);
return true;
}
diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
index 864bbad3..2647801c 100644
--- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc
@@ -117,10 +117,10 @@ bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
if (total_length >= NAME_MAX)
return false;
- memcpy(path, "/proc/", 6);
+ my_memcpy(path, "/proc/", 6);
my_itos(path + 6, pid, pid_len);
path[6 + pid_len] = '/';
- memcpy(path + 6 + pid_len + 1, node, node_len);
+ my_memcpy(path + 6 + pid_len + 1, node, node_len);
path[total_length] = '\0';
return true;
}
@@ -138,7 +138,7 @@ void LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
tmp = 0;
}
- memcpy(local + done, &tmp, l);
+ my_memcpy(local + done, &tmp, l);
done += l;
}
}
@@ -212,11 +212,11 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
const uint8_t* stack_pointer;
#if defined(__i386)
- memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
+ my_memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
#elif defined(__x86_64)
- memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
+ my_memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
- memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
+ my_memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
#else
#error "This code hasn't been ported to your platform yet."
#endif
@@ -237,8 +237,8 @@ bool LinuxPtraceDumper::ThreadsSuspend() {
// If the thread either disappeared before we could attach to it, or if
// it was part of the seccomp sandbox's trusted code, it is OK to
// silently drop it from the minidump.
- memmove(&threads_[i], &threads_[i+1],
- (threads_.size() - i - 1) * sizeof(threads_[i]));
+ my_memmove(&threads_[i], &threads_[i+1],
+ (threads_.size() - i - 1) * sizeof(threads_[i]));
threads_.resize(threads_.size() - 1);
--i;
}
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index e0aeb3bd..89fc96ff 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -91,14 +91,14 @@ typedef MDRawContextX86 RawContextCPU;
// out: memory location to write to
// v: value to write.
static void U16(void* out, uint16_t v) {
- memcpy(out, &v, sizeof(v));
+ my_memcpy(out, &v, sizeof(v));
}
// Write a uint32_t to memory
// out: memory location to write to
// v: value to write.
static void U32(void* out, uint32_t v) {
- memcpy(out, &v, sizeof(v));
+ my_memcpy(out, &v, sizeof(v));
}
// Juggle an x86 user_(fp|fpx|)regs_struct into minidump format
@@ -145,7 +145,7 @@ static void CPUFillFromThreadInfo(MDRawContextX86 *out,
out->float_save.data_selector = info.fpregs.fos;
// 8 registers * 10 bytes per register.
- memcpy(out->float_save.register_area, info.fpregs.st_space, 10 * 8);
+ my_memcpy(out->float_save.register_area, info.fpregs.st_space, 10 * 8);
// This matches the Intel fpsave format.
U16(out->extended_registers + 0, info.fpregs.cwd);
@@ -158,8 +158,8 @@ static void CPUFillFromThreadInfo(MDRawContextX86 *out,
U16(out->extended_registers + 20, info.fpregs.fos);
U32(out->extended_registers + 24, info.fpxregs.mxcsr);
- memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128);
- memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128);
+ my_memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128);
+ my_memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128);
}
// Juggle an x86 ucontext into minidump format
@@ -200,7 +200,7 @@ static void CPUFillFromUContext(MDRawContextX86 *out, const ucontext *uc,
out->float_save.data_selector = fp->datasel;
// 8 registers * 10 bytes per register.
- memcpy(out->float_save.register_area, fp->_st, 10 * 8);
+ my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
}
#elif defined(__x86_64)
@@ -261,8 +261,8 @@ static void CPUFillFromThreadInfo(MDRawContextAMD64 *out,
out->flt_save.data_selector = 0; // We don't have this.
out->flt_save.mx_csr = info.fpregs.mxcsr;
out->flt_save.mx_csr_mask = info.fpregs.mxcr_mask;
- memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16);
- memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16);
+ my_memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16);
}
static void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc,
@@ -308,8 +308,8 @@ static void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc,
out->flt_save.data_selector = 0; // We don't have this.
out->flt_save.mx_csr = fpregs->mxcsr;
out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
- memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
- memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
+ my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
+ my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
}
#elif defined(__ARMEL__)
@@ -327,8 +327,8 @@ static void CPUFillFromThreadInfo(MDRawContextARM *out,
out->float_save.fpscr = info.fpregs.fpsr |
(static_cast<u_int64_t>(info.fpregs.fpcr) << 32);
// TODO: sort this out, actually collect floating point registers
- memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
- memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
#endif
}
@@ -358,8 +358,8 @@ static void CPUFillFromUContext(MDRawContextARM *out, const ucontext *uc,
// TODO: fix this after fixing ExceptionHandler
out->float_save.fpscr = 0;
- memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
- memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+ my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
+ my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
}
#else
@@ -439,7 +439,7 @@ class MinidumpWriter {
return false;
if (!dir.AllocateArray(kNumWriters))
return false;
- memset(header.get(), 0, sizeof(MDRawHeader));
+ my_memset(header.get(), 0, sizeof(MDRawHeader));
header.get()->signature = MD_HEADER_SIGNATURE;
header.get()->version = MD_HEADER_VERSION;
@@ -537,7 +537,7 @@ class MinidumpWriter {
uint64_t old_top = top;
top = bp;
u_int8_t* bp_addr = stack_copy + bp - thread.stack.start_of_memory_range;
- memcpy(&bp, bp_addr, sizeof(bp));
+ my_memcpy(&bp, bp_addr, sizeof(bp));
if (bp == 0xDEADBEEFDEADBEEFull) {
struct {
uint64_t r15;
@@ -565,9 +565,9 @@ class MinidumpWriter {
thread.stack.start_of_memory_range+thread.stack.memory.data_size) {
break;
}
- memcpy(&seccomp_stackframe,
- bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
- sizeof(seccomp_stackframe));
+ my_memcpy(&seccomp_stackframe,
+ bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
+ sizeof(seccomp_stackframe));
cpu->rbx = seccomp_stackframe.rbx;
cpu->rcx = seccomp_stackframe.rcx;
cpu->rdx = seccomp_stackframe.rdx;
@@ -600,7 +600,7 @@ class MinidumpWriter {
uint32_t old_top = top;
top = bp;
u_int8_t* bp_addr = stack_copy + bp - thread.stack.start_of_memory_range;
- memcpy(&bp, bp_addr, sizeof(bp));
+ my_memcpy(&bp, bp_addr, sizeof(bp));
if (bp == 0xDEADBEEFu) {
struct {
uint32_t edi;
@@ -619,9 +619,9 @@ class MinidumpWriter {
thread.stack.start_of_memory_range+thread.stack.memory.data_size) {
break;
}
- memcpy(&seccomp_stackframe,
- bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
- sizeof(seccomp_stackframe));
+ my_memcpy(&seccomp_stackframe,
+ bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
+ sizeof(seccomp_stackframe));
cpu->ebx = seccomp_stackframe.ebx;
cpu->ecx = seccomp_stackframe.ecx;
cpu->edx = seccomp_stackframe.edx;
@@ -865,13 +865,13 @@ class MinidumpWriter {
return false;
const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
- memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
+ my_memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
cv_ptr += sizeof(cv_signature);
uint8_t* signature = cv_ptr;
cv_ptr += sizeof(MDGUID);
if (identifier) {
// GUID was provided by caller.
- memcpy(signature, identifier, sizeof(MDGUID));
+ my_memcpy(signature, identifier, sizeof(MDGUID));
} else {
dumper_->ElfFileIdentifierForMapping(mapping, member,
mapping_id, signature);
@@ -880,7 +880,7 @@ class MinidumpWriter {
cv_ptr += sizeof(uint32_t);
// Write pdb_file_name
- memcpy(cv_ptr, filename_ptr, filename_len + 1);
+ my_memcpy(cv_ptr, filename_ptr, filename_len + 1);
cv.Copy(cv_buf, MDCVInfoPDB70_minsize + filename_len + 1);
mod.cv_record = cv.location();
@@ -1110,8 +1110,8 @@ class MinidumpWriter {
CpuInfoEntry* entry = &cpu_info_table[i];
if (entry->found && i)
continue;
- if (!strncmp(line, entry->info_name, strlen(entry->info_name))) {
- const char* value = strchr(line, ':');
+ if (!my_strncmp(line, entry->info_name, strlen(entry->info_name))) {
+ const char* value = my_strchr(line, ':');
if (!value)
continue;
@@ -1119,33 +1119,35 @@ class MinidumpWriter {
// line. i.e. we matched "model name" instead of "model".
// check and make sure there is only spaces between the prefix and
// the colon.
- const char* space_ptr = line + strlen(entry->info_name);
+ const char* space_ptr = line + my_strlen(entry->info_name);
for (; space_ptr < value; space_ptr++) {
- if (!isspace(*space_ptr)) {
+ if (!my_isspace(*space_ptr)) {
break;
}
}
if (space_ptr != value)
continue;
- sscanf(++value, " %d", &(entry->value));
+ uintptr_t val;
+ my_read_decimal_ptr(&val, ++value);
+ entry->value = static_cast<int>(val);
entry->found = true;
}
}
// special case for vendor_id
- if (!strncmp(line, vendor_id_name, vendor_id_name_length)) {
- const char* value = strchr(line, ':');
+ if (!my_strncmp(line, vendor_id_name, vendor_id_name_length)) {
+ const char* value = my_strchr(line, ':');
if (!value)
goto popline;
// skip ':" and all the spaces that follows
do {
value++;
- } while (isspace(*value));
+ } while (my_isspace(*value));
if (*value) {
- size_t length = strlen(value);
+ size_t length = my_strlen(value);
if (length == 0)
goto popline;
// we don't want the trailing newline
@@ -1153,7 +1155,7 @@ class MinidumpWriter {
length--;
// ensure we have space for the value
if (length < sizeof(vendor_id))
- strncpy(vendor_id, value, length);
+ my_strlcpy(vendor_id, value, length);
}
}
@@ -1180,8 +1182,8 @@ class MinidumpWriter {
cpu_info_table[2].value;
if (vendor_id[0] != '\0') {
- memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
- sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
+ my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
+ sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
}
return true;
}
@@ -1270,9 +1272,9 @@ class MinidumpWriter {
};
bool first_item = true;
for (const char** cur_info = info_table; *cur_info; cur_info++) {
- static const char* separator = " ";
- size_t separator_len = strlen(separator);
- size_t info_len = strlen(*cur_info);
+ static const char separator[] = " ";
+ size_t separator_len = sizeof(separator) - 1;
+ size_t info_len = my_strlen(*cur_info);
if (info_len == 0)
continue;
@@ -1280,12 +1282,12 @@ class MinidumpWriter {
break;
if (!first_item) {
- strcat(buf, separator);
+ my_strlcat(buf, separator, sizeof(buf));
space_left -= separator_len;
}
first_item = false;
- strcat(buf, *cur_info);
+ my_strlcat(buf, *cur_info, sizeof(buf));
space_left -= info_len;
}
@@ -1301,8 +1303,8 @@ class MinidumpWriter {
if (fingerprint_len > 0 && fingerprint_len < PROP_VALUE_MAX) {
const char* separator = " ";
if (!first_item)
- strlcat(buf, separator, buf_len);
- strlcat(buf, fingerprint, buf_len);
+ my_strlcat(buf, separator, sizeof(buf));
+ my_strlcat(buf, fingerprint, sizeof(buf));
}
#endif
diff --git a/src/common/linux/linux_libc_support.h b/src/common/linux/linux_libc_support.h
index 2ef2dc11..b2f47af8 100644
--- a/src/common/linux/linux_libc_support.h
+++ b/src/common/linux/linux_libc_support.h
@@ -40,83 +40,21 @@
extern "C" {
-static inline size_t
-my_strlen(const char* s) {
- size_t len = 0;
- while (*s++) len++;
- return len;
-}
-
-static inline int
-my_strcmp(const char* a, const char* b) {
- for (;;) {
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- else if (*a == 0)
- return 0;
- a++;
- b++;
- }
-}
-
-static inline int
-my_strncmp(const char* a, const char* b, size_t len) {
- for (size_t i = 0; i < len; ++i) {
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- else if (*a == 0)
- return 0;
- a++;
- b++;
- }
-
- return 0;
-}
+extern size_t my_strlen(const char* s);
+
+extern int my_strcmp(const char* a, const char* b);
+
+extern int my_strncmp(const char* a, const char* b, size_t len);
// Parse a non-negative integer.
// result: (output) the resulting non-negative integer
// s: a NUL terminated string
// Return true iff successful.
-static inline bool
-my_strtoui(int* result, const char* s) {
- if (*s == 0)
- return false;
- int r = 0;
- for (;; s++) {
- if (*s == 0)
- break;
- const int old_r = r;
- r *= 10;
- if (*s < '0' || *s > '9')
- return false;
- r += *s - '0';
- if (r < old_r)
- return false;
- }
-
- *result = r;
- return true;
-}
+extern bool my_strtoui(int* result, const char* s);
// Return the length of the given, non-negative integer when expressed in base
// 10.
-static inline unsigned
-my_int_len(intmax_t i) {
- if (!i)
- return 1;
-
- int len = 0;
- while (i) {
- len++;
- i /= 10;
- }
-
- return len;
-}
+extern unsigned my_int_len(intmax_t i);
// Convert a non-negative integer to a string
// output: (output) the resulting string is written here. This buffer must be
@@ -124,54 +62,33 @@ my_int_len(intmax_t i) {
// required length.
// i: the non-negative integer to serialise.
// i_len: the length of the integer in base 10 (see |my_int_len|).
-static inline void
-my_itos(char* output, intmax_t i, unsigned i_len) {
- for (unsigned index = i_len; index; --index, i /= 10)
- output[index - 1] = '0' + (i % 10);
-}
-
-static inline const char*
-my_strchr(const char* haystack, char needle) {
- while (*haystack && *haystack != needle)
- haystack++;
- if (*haystack == needle)
- return haystack;
- return (const char*) 0;
-}
+extern void my_itos(char* output, intmax_t i, unsigned i_len);
+
+extern const char* my_strchr(const char* haystack, char needle);
+
+extern const char* my_strrchr(const char* haystack, char needle);
// Read a hex value
// result: (output) the resulting value
// s: a string
// Returns a pointer to the first invalid charactor.
-static inline const char*
-my_read_hex_ptr(uintptr_t* result, const char* s) {
- uintptr_t r = 0;
-
- for (;; ++s) {
- if (*s >= '0' && *s <= '9') {
- r <<= 4;
- r += *s - '0';
- } else if (*s >= 'a' && *s <= 'f') {
- r <<= 4;
- r += (*s - 'a') + 10;
- } else if (*s >= 'A' && *s <= 'F') {
- r <<= 4;
- r += (*s - 'A') + 10;
- } else {
- break;
- }
- }
-
- *result = r;
- return s;
-}
-
-static inline void
-my_memset(void* ip, char c, size_t len) {
- char* p = (char *) ip;
- while (len--)
- *p++ = c;
-}
+extern const char* my_read_hex_ptr(uintptr_t* result, const char* s);
+
+extern const char* my_read_decimal_ptr(uintptr_t* result, const char* s);
+
+extern void my_memset(void* ip, char c, size_t len);
+
+// The following are considered safe to use in a compromised environment.
+// Besides, this gives the compiler an opportunity to optimize their calls.
+#define my_memcpy memcpy
+#define my_memmove memmove
+#define my_memcmp memcmp
+
+extern size_t my_strlcpy(char* s1, const char* s2, size_t len);
+
+extern size_t my_strlcat(char* s1, const char* s2, size_t len);
+
+extern int my_isspace(int ch);
} // extern "C"
diff --git a/src/common/linux/linux_libc_support_unittest.cc b/src/common/linux/linux_libc_support_unittest.cc
index 6f4b2da6..7f974af8 100644
--- a/src/common/linux/linux_libc_support_unittest.cc
+++ b/src/common/linux/linux_libc_support_unittest.cc
@@ -129,6 +129,23 @@ TEST(LinuxLibcSupportTest, strchr) {
ASSERT_TRUE(my_strchr("abc", 'a'));
ASSERT_TRUE(my_strchr("bcda", 'a'));
ASSERT_TRUE(my_strchr("sdfasdf", 'a'));
+
+ static const char abc3[] = "abcabcabc";
+ ASSERT_EQ(abc3, my_strchr(abc3, 'a'));
+}
+
+TEST(LinuxLibcSupportTest, strrchr) {
+ ASSERT_EQ(NULL, my_strrchr("abc", 'd'));
+ ASSERT_EQ(NULL, my_strrchr("", 'd'));
+ ASSERT_EQ(NULL, my_strrchr("efghi", 'd'));
+
+ ASSERT_TRUE(my_strrchr("a", 'a'));
+ ASSERT_TRUE(my_strrchr("abc", 'a'));
+ ASSERT_TRUE(my_strrchr("bcda", 'a'));
+ ASSERT_TRUE(my_strrchr("sdfasdf", 'a'));
+
+ static const char abc3[] = "abcabcabc";
+ ASSERT_EQ(abc3 + 6, my_strrchr(abc3, 'a'));
}
TEST(LinuxLibcSupportTest, read_hex_ptr) {
@@ -155,3 +172,24 @@ TEST(LinuxLibcSupportTest, read_hex_ptr) {
ASSERT_EQ(result, 0x123a);
ASSERT_EQ(*last, '-');
}
+
+TEST(LinuxLibcSupportTest, read_decimal_ptr) {
+ uintptr_t result;
+ const char* last;
+
+ last = my_read_decimal_ptr(&result, "0");
+ ASSERT_EQ(result, 0);
+ ASSERT_EQ(*last, 0);
+
+ last = my_read_decimal_ptr(&result, "0123");
+ ASSERT_EQ(result, 123);
+ ASSERT_EQ(*last, 0);
+
+ last = my_read_decimal_ptr(&result, "1234");
+ ASSERT_EQ(result, 1234);
+ ASSERT_EQ(*last, 0);
+
+ last = my_read_decimal_ptr(&result, "01234-");
+ ASSERT_EQ(result, 1234);
+ ASSERT_EQ(*last, '-');
+}