log_event_list.c revision 9dd6510dd09f40973b8834c5cad1217ce1c3011d
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <errno.h> 18#include <inttypes.h> 19#include <stdbool.h> 20#include <stdint.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24 25#include <log/log.h> 26#include <log/logger.h> 27 28#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t)) 29 30typedef struct { 31 uint32_t tag; 32 unsigned pos; /* Read/write position into buffer */ 33 unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */ 34 unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */ 35 unsigned list_nest_depth; 36 unsigned len; /* Length or raw buffer. */ 37 bool overflow; 38 bool list_stop; /* next call decrement list_nest_depth and issue a stop */ 39 enum { 40 kAndroidLoggerRead = 1, 41 kAndroidLoggerWrite = 2, 42 } read_write_flag; 43 uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD]; 44} android_log_context_internal; 45 46android_log_context create_android_logger(uint32_t tag) { 47 size_t needed, i; 48 android_log_context_internal *context; 49 50 context = calloc(1, sizeof(android_log_context_internal)); 51 if (!context) { 52 return NULL; 53 } 54 context->tag = tag; 55 context->read_write_flag = kAndroidLoggerWrite; 56 needed = sizeof(uint8_t) + sizeof(uint8_t); 57 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 58 context->overflow = true; 59 } 60 /* Everything is a list */ 61 context->storage[context->pos + 0] = EVENT_TYPE_LIST; 62 context->list[0] = context->pos + 1; 63 context->pos += needed; 64 65 return (android_log_context)context; 66} 67 68android_log_context create_android_log_parser(const char *msg, size_t len) { 69 android_log_context_internal *context; 70 size_t i; 71 72 context = calloc(1, sizeof(android_log_context_internal)); 73 if (!context) { 74 return NULL; 75 } 76 len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD; 77 context->len = len; 78 memcpy(context->storage, msg, len); 79 context->read_write_flag = kAndroidLoggerRead; 80 81 return (android_log_context)context; 82} 83 84int android_log_destroy(android_log_context *ctx) { 85 android_log_context_internal *context; 86 87 context = (android_log_context_internal *)*ctx; 88 if (!context) { 89 return -EBADF; 90 } 91 memset(context, 0, sizeof(*context)); 92 free(context); 93 *ctx = NULL; 94 return 0; 95} 96 97int android_log_write_list_begin(android_log_context ctx) { 98 size_t needed; 99 android_log_context_internal *context; 100 101 context = (android_log_context_internal *)ctx; 102 if (!context || 103 (kAndroidLoggerWrite != context->read_write_flag)) { 104 return -EBADF; 105 } 106 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { 107 context->overflow = true; 108 return -EOVERFLOW; 109 } 110 needed = sizeof(uint8_t) + sizeof(uint8_t); 111 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 112 context->overflow = true; 113 return -EIO; 114 } 115 context->count[context->list_nest_depth]++; 116 context->list_nest_depth++; 117 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { 118 context->overflow = true; 119 return -EOVERFLOW; 120 } 121 if (context->overflow) { 122 return -EIO; 123 } 124 context->storage[context->pos + 0] = EVENT_TYPE_LIST; 125 context->storage[context->pos + 1] = 0; 126 context->list[context->list_nest_depth] = context->pos + 1; 127 context->count[context->list_nest_depth] = 0; 128 context->pos += needed; 129 return 0; 130} 131 132static inline void copy4LE(uint8_t *buf, uint32_t val) 133{ 134 buf[0] = val & 0xFF; 135 buf[1] = (val >> 8) & 0xFF; 136 buf[2] = (val >> 16) & 0xFF; 137 buf[3] = (val >> 24) & 0xFF; 138} 139 140int android_log_write_int32(android_log_context ctx, int32_t value) { 141 size_t needed; 142 android_log_context_internal *context; 143 144 context = (android_log_context_internal *)ctx; 145 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 146 return -EBADF; 147 } 148 if (context->overflow) { 149 return -EIO; 150 } 151 needed = sizeof(uint8_t) + sizeof(value); 152 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 153 context->overflow = true; 154 return -EIO; 155 } 156 context->count[context->list_nest_depth]++; 157 context->storage[context->pos + 0] = EVENT_TYPE_INT; 158 copy4LE(&context->storage[context->pos + 1], value); 159 context->pos += needed; 160 return 0; 161} 162 163static inline void copy8LE(uint8_t *buf, uint64_t val) 164{ 165 buf[0] = val & 0xFF; 166 buf[1] = (val >> 8) & 0xFF; 167 buf[2] = (val >> 16) & 0xFF; 168 buf[3] = (val >> 24) & 0xFF; 169 buf[4] = (val >> 32) & 0xFF; 170 buf[5] = (val >> 40) & 0xFF; 171 buf[6] = (val >> 48) & 0xFF; 172 buf[7] = (val >> 56) & 0xFF; 173} 174 175int android_log_write_int64(android_log_context ctx, int64_t value) { 176 size_t needed; 177 android_log_context_internal *context; 178 179 context = (android_log_context_internal *)ctx; 180 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 181 return -EBADF; 182 } 183 if (context->overflow) { 184 return -EIO; 185 } 186 needed = sizeof(uint8_t) + sizeof(value); 187 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 188 context->overflow = true; 189 return -EIO; 190 } 191 context->count[context->list_nest_depth]++; 192 context->storage[context->pos + 0] = EVENT_TYPE_LONG; 193 copy8LE(&context->storage[context->pos + 1], value); 194 context->pos += needed; 195 return 0; 196} 197 198int android_log_write_string8(android_log_context ctx, const char *value) { 199 size_t needed; 200 int32_t len; 201 android_log_context_internal *context; 202 203 context = (android_log_context_internal *)ctx; 204 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 205 return -EBADF; 206 } 207 if (context->overflow) { 208 return -EIO; 209 } 210 if (!value) { 211 return -EINVAL; 212 } 213 len = strlen(value); 214 needed = sizeof(uint8_t) + sizeof(len) + len; 215 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 216 /* Truncate string for delivery */ 217 len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(len); 218 if (len <= 0) { 219 context->overflow = true; 220 return -EIO; 221 } 222 } 223 context->count[context->list_nest_depth]++; 224 context->storage[context->pos + 0] = EVENT_TYPE_STRING; 225 copy4LE(&context->storage[context->pos + 1], len); 226 memcpy(&context->storage[context->pos + 5], value, len); 227 context->pos += needed; 228 return 0; 229} 230 231int android_log_write_float32(android_log_context ctx, float value) { 232 size_t needed; 233 uint32_t ivalue; 234 android_log_context_internal *context; 235 236 context = (android_log_context_internal *)ctx; 237 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 238 return -EBADF; 239 } 240 if (context->overflow) { 241 return -EIO; 242 } 243 needed = sizeof(uint8_t) + sizeof(ivalue); 244 if ((context->pos + needed) > MAX_EVENT_PAYLOAD) { 245 context->overflow = true; 246 return -EIO; 247 } 248 ivalue = *(uint32_t *)&value; 249 context->count[context->list_nest_depth]++; 250 context->storage[context->pos + 0] = EVENT_TYPE_FLOAT; 251 copy4LE(&context->storage[context->pos + 1], ivalue); 252 context->pos += needed; 253 return 0; 254} 255 256int android_log_write_list_end(android_log_context ctx) { 257 android_log_context_internal *context; 258 259 context = (android_log_context_internal *)ctx; 260 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 261 return -EBADF; 262 } 263 if (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) { 264 context->overflow = true; 265 context->list_nest_depth--; 266 return -EOVERFLOW; 267 } 268 if (!context->list_nest_depth) { 269 context->overflow = true; 270 return -EOVERFLOW; 271 } 272 if (context->list[context->list_nest_depth] <= 0) { 273 context->list_nest_depth--; 274 context->overflow = true; 275 return -EOVERFLOW; 276 } 277 context->storage[context->list[context->list_nest_depth]] = 278 context->count[context->list_nest_depth]; 279 context->list_nest_depth--; 280 return 0; 281} 282 283/* 284 * Logs the list of elements to the event log. 285 */ 286int android_log_write_list(android_log_context ctx, log_id_t id) { 287 android_log_context_internal *context; 288 const char *msg; 289 ssize_t len; 290 291 if ((id != LOG_ID_EVENTS) && (id != LOG_ID_SECURITY)) { 292 return -EINVAL; 293 } 294 295 context = (android_log_context_internal *)ctx; 296 if (!context || (kAndroidLoggerWrite != context->read_write_flag)) { 297 return -EBADF; 298 } 299 if (context->list_nest_depth) { 300 return -EIO; 301 } 302 /* NB: if there was overflow, then log is truncated. Nothing reported */ 303 context->storage[1] = context->count[0]; 304 len = context->len = context->pos; 305 msg = (const char *)context->storage; 306 /* it'snot a list */ 307 if (context->count[0] <= 1) { 308 len -= sizeof(uint8_t) + sizeof(uint8_t); 309 if (len < 0) { 310 len = 0; 311 } 312 msg += sizeof(uint8_t) + sizeof(uint8_t); 313 } 314 return (id == LOG_ID_EVENTS) ? 315 __android_log_bwrite(context->tag, msg, len) : 316 __android_log_security_bwrite(context->tag, msg, len); 317} 318 319/* 320 * Extract a 4-byte value from a byte stream. 321 */ 322static inline uint32_t get4LE(const uint8_t* src) 323{ 324 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); 325} 326 327/* 328 * Extract an 8-byte value from a byte stream. 329 */ 330static inline uint64_t get8LE(const uint8_t* src) 331{ 332 uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); 333 uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24); 334 return ((uint64_t) high << 32) | (uint64_t) low; 335} 336 337/* 338 * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type. 339 * If there is nothing to process, the complete field is set to non-zero. If 340 * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check 341 * this and continues to call this function, the behavior is undefined 342 * (although it won't crash). 343 */ 344static android_log_list_element android_log_read_next_internal( 345 android_log_context ctx, int peek) { 346 android_log_list_element elem; 347 unsigned pos; 348 android_log_context_internal *context; 349 350 context = (android_log_context_internal *)ctx; 351 352 memset(&elem, 0, sizeof(elem)); 353 354 /* Nothing to parse from this context, so return complete. */ 355 if (!context || (kAndroidLoggerRead != context->read_write_flag) || 356 (context->list_nest_depth > ANDROID_MAX_LIST_NEST_DEPTH) || 357 (context->count[context->list_nest_depth] >= 358 (MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) { 359 elem.type = EVENT_TYPE_UNKNOWN; 360 if (context && 361 (context->list_stop || 362 ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) && 363 !context->count[context->list_nest_depth]))) { 364 elem.type = EVENT_TYPE_LIST_STOP; 365 } 366 elem.complete = true; 367 return elem; 368 } 369 370 /* 371 * Use a different variable to update the position in case this 372 * operation is a "peek". 373 */ 374 pos = context->pos; 375 if (context->list_stop) { 376 elem.type = EVENT_TYPE_LIST_STOP; 377 elem.complete = !context->count[0] && (!context->list_nest_depth || 378 ((context->list_nest_depth == 1) && !context->count[1])); 379 if (!peek) { 380 /* Suck in superfluous stop */ 381 if (context->storage[pos] == EVENT_TYPE_LIST_STOP) { 382 context->pos = pos + 1; 383 } 384 if (context->list_nest_depth) { 385 --context->list_nest_depth; 386 if (context->count[context->list_nest_depth]) { 387 context->list_stop = false; 388 } 389 } else { 390 context->list_stop = false; 391 } 392 } 393 return elem; 394 } 395 if ((pos + 1) > context->len) { 396 elem.type = EVENT_TYPE_UNKNOWN; 397 elem.complete = true; 398 return elem; 399 } 400 401 elem.type = context->storage[pos++]; 402 switch ((int)elem.type) { 403 case EVENT_TYPE_FLOAT: 404 /* Rely on union to translate elem.data.int32 into elem.data.float32 */ 405 /* FALLTHRU */ 406 case EVENT_TYPE_INT: 407 elem.len = sizeof(int32_t); 408 if ((pos + elem.len) > context->len) { 409 elem.type = EVENT_TYPE_UNKNOWN; 410 return elem; 411 } 412 elem.data.int32 = get4LE(&context->storage[pos]); 413 /* common tangeable object suffix */ 414 pos += elem.len; 415 elem.complete = !context->list_nest_depth && !context->count[0]; 416 if (!peek) { 417 if (!context->count[context->list_nest_depth] || 418 !--(context->count[context->list_nest_depth])) { 419 context->list_stop = true; 420 } 421 context->pos = pos; 422 } 423 return elem; 424 425 case EVENT_TYPE_LONG: 426 elem.len = sizeof(int64_t); 427 if ((pos + elem.len) > context->len) { 428 elem.type = EVENT_TYPE_UNKNOWN; 429 return elem; 430 } 431 elem.data.int64 = get8LE(&context->storage[pos]); 432 /* common tangeable object suffix */ 433 pos += elem.len; 434 elem.complete = !context->list_nest_depth && !context->count[0]; 435 if (!peek) { 436 if (!context->count[context->list_nest_depth] || 437 !--(context->count[context->list_nest_depth])) { 438 context->list_stop = true; 439 } 440 context->pos = pos; 441 } 442 return elem; 443 444 case EVENT_TYPE_STRING: 445 if ((pos + sizeof(int32_t)) > context->len) { 446 elem.type = EVENT_TYPE_UNKNOWN; 447 elem.complete = true; 448 return elem; 449 } 450 elem.len = get4LE(&context->storage[pos]); 451 pos += sizeof(int32_t); 452 if ((pos + elem.len) > context->len) { 453 elem.len = context->len - pos; /* truncate string */ 454 elem.complete = true; 455 if (!elem.len) { 456 elem.type = EVENT_TYPE_UNKNOWN; 457 return elem; 458 } 459 } 460 elem.data.string = (char *)&context->storage[pos]; 461 /* common tangeable object suffix */ 462 pos += elem.len; 463 elem.complete = !context->list_nest_depth && !context->count[0]; 464 if (!peek) { 465 if (!context->count[context->list_nest_depth] || 466 !--(context->count[context->list_nest_depth])) { 467 context->list_stop = true; 468 } 469 context->pos = pos; 470 } 471 return elem; 472 473 case EVENT_TYPE_LIST: 474 if ((pos + sizeof(uint8_t)) > context->len) { 475 elem.type = EVENT_TYPE_UNKNOWN; 476 elem.complete = true; 477 return elem; 478 } 479 elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH; 480 if (peek) { 481 return elem; 482 } 483 if (context->count[context->list_nest_depth]) { 484 context->count[context->list_nest_depth]--; 485 } 486 context->list_stop = !context->storage[pos]; 487 context->list_nest_depth++; 488 if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) { 489 context->count[context->list_nest_depth] = context->storage[pos]; 490 } 491 context->pos = pos + sizeof(uint8_t); 492 return elem; 493 494 case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */ 495 if (!peek) { 496 context->pos = pos; 497 } 498 elem.type = EVENT_TYPE_UNKNOWN; 499 elem.complete = !context->list_nest_depth; 500 if (context->list_nest_depth > 0) { 501 elem.type = EVENT_TYPE_LIST_STOP; 502 if (!peek) { 503 context->list_nest_depth--; 504 } 505 } 506 return elem; 507 508 default: 509 elem.type = EVENT_TYPE_UNKNOWN; 510 return elem; 511 } 512} 513 514android_log_list_element android_log_read_next(android_log_context ctx) { 515 return android_log_read_next_internal(ctx, 0); 516} 517 518android_log_list_element android_log_peek_next(android_log_context ctx) { 519 return android_log_read_next_internal(ctx, 1); 520} 521