static kdump_status do_notes(kdump_ctx *ctx, void *data, size_t size, do_note_fn *do_note) { Elf32_Nhdr *hdr = data; kdump_status ret = kdump_ok; while (ret == kdump_ok && size >= sizeof(Elf32_Nhdr)) { char *name, *desc; Elf32_Word namesz = dump32toh(ctx, hdr->n_namesz); Elf32_Word descsz = dump32toh(ctx, hdr->n_descsz); Elf32_Word type = dump32toh(ctx, hdr->n_type); size_t descoff = sizeof(Elf32_Nhdr) + roundup_size(namesz); if (size < descoff + descsz) break; name = (char*) (hdr + 1); desc = (char*)hdr + descoff; size -= descoff; hdr = (Elf32_Nhdr*) (desc + roundup_size(descsz)); size = (size >= roundup_size(descsz)) ? size - roundup_size(descsz) : 0; ret = do_note(ctx, type, name, namesz, desc, descsz); } return ret; }
expstring_t mprintf_va_list(const char *fmt, va_list pvar) #endif { char buf[BUFSIZE]; expstring_t ptr; int len; size_t size, slen; va_list pvar2; va_copy(pvar2, pvar); len = vsnprintf(buf, BUFSIZE, fmt, pvar2); va_end(pvar2); if (len < 0) { /* The result does not fit in buf and we have no idea how many bytes * are needed (only old versions of libc may return -1). * Try to double the buffer size until it is large enough. */ for (size = 2 * BUFSIZE; ; size *= 2) { ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); va_copy(pvar2, pvar); len = vsnprintf(ptr, size, fmt, pvar2); va_end(pvar2); if (len >= 0 && (size_t)len < size) break; FREE_INTERNAL(filename, line, ptr); } slen = (size_t)len; } else if (len >= BUFSIZE) { /* The result does not fit in buf, but we know how many bytes we need. * Allocate a buffer that is large enough and repeat vsnprintf() */ slen = (size_t)len; size = roundup_size(slen); ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); /* use the original pvar since this is the last try */ if (vsnprintf(ptr, size, fmt, pvar) != len) { perror("Fatal error: unexpected vsnprintf() return value"); exit(EXIT_FAILURE); } } else { /* the complete result is in buf */ slen = (size_t)len; size = roundup_size(slen); ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); memcpy(ptr, buf, slen); } memset(ptr + slen, '\0', size - slen); return ptr; }
expstring_t mcopystrn(const char *str, size_t len) #endif { if (len != 0 && str != NULL) { size_t size = roundup_size(len); expstring_t ptr = (expstring_t)MALLOC_INTERNAL(filename, line, size); memcpy(ptr, str, len); memset(ptr + len, '\0', size - len); return ptr; } else return MEMPTYSTR_INTERNAL(filename, line); }
/* Tracking the origin: extracts the filename/line from the original allocation * of the expstring_t. */ expstring_t mputprintf_va_list(expstring_t str, const char *fmt, va_list pvar) { const char *filename = NULL; int line = 0; if (str != NULL) { size_t size; size_t len = fast_strlen(str, &size); size_t rest = size - len; int len2; va_list pvar2; /* make a copy of pvar to allow re-use later */ va_copy(pvar2, pvar); len2 = vsnprintf(str + len, rest, fmt, pvar2); va_end(pvar2); extract_location(str, &filename, &line); if (len2 < 0) { /* the result does not fit in buf and we have no idea how many * bytes are needed (only old versions of libc may return -1) * try to double the buffer size until it is large enough */ size_t newlen; do { size *= 2; str = (expstring_t)REALLOC_INTERNAL(filename, line, str, size); rest = size - len; va_copy(pvar2, pvar); len2 = vsnprintf(str + len, rest, fmt, pvar2); va_end(pvar2); } while (len2 < 0 || (size_t)len2 >= rest); newlen = len + (size_t)len2; memset(str + newlen, '\0', size - newlen); } else if ((size_t)len2 >= rest) { /* there isn't enough space in buffer, but we know how many bytes * we need: reallocate the buffer to be large enough and repeat * vsnprintf() */ size_t newlen = len + (size_t)len2; size = roundup_size(newlen); str = (expstring_t)REALLOC_INTERNAL(filename, line, str, size); /* use the original pvar since this is the last try */ if (vsnprintf(str + len, size - len, fmt, pvar) != len2) { perror("Fatal error: unexpected vsnprintf() return value"); exit(EXIT_FAILURE); } memset(str + newlen, '\0', size - newlen); } } else str = MPRINTF_VA_LIST_INTERNAL(filename, line, fmt, pvar); return str; }
/* Tracking the origin: extracts the filename/line from the original allocation * of the expstring_t. */ expstring_t mtruncstr(expstring_t str, size_t newlen) { const char *filename = NULL; int line = 0; if (str != NULL) { size_t size; size_t len = fast_strlen(str, &size); if (newlen < len) { size_t newsize = roundup_size(newlen); if (newsize < size) { extract_location(str, &filename, &line); str = (expstring_t)REALLOC_INTERNAL(filename, line, str, newsize); } memset(str + newlen, '\0', newsize - newlen); } } return str; }
/* Tracking the origin: extracts the filename/line from the original allocation * of the expstring_t. */ expstring_t mputstrn(expstring_t str, const char *str2, size_t len2) { const char *filename = NULL; int line = 0; if (len2 != 0 && str2 != NULL) { if (str != NULL) { size_t size; size_t len = fast_strlen(str, &size); size_t newlen = len + len2; if (size <= newlen) { size_t newsize = roundup_size(newlen); extract_location(str, &filename, &line); str = (expstring_t)REALLOC_INTERNAL(filename, line, str, newsize); memset(str + newlen, '\0', newsize - newlen); } memcpy(str + len, str2, len2); } else str = MCOPYSTR_INTERNAL(filename, line, str2); } return str; }