"Fossies" - the Fresh Open Source Software Archive

Member "virt-dmesg-0.3.0/src/c_utils.c" (25 May 2011, 7774 Bytes) of package /linux/privat/old/virt-dmesg-0.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* virt-dmesg
    2  * (C) Copyright 2008-2011 Red Hat Inc.
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17  */
   18 
   19 /* This contains functions written in C.  We can drop into C wherever
   20  * we need to do something that would be much faster than OCaml or
   21  * where it's just awkward to do something in OCaml or much easier in
   22  * C.
   23  */
   24 
   25 #include <config.h>
   26 
   27 #include <stdio.h>
   28 #include <stdlib.h>
   29 #include <stdint.h>
   30 #include <string.h>
   31 #include <inttypes.h>
   32 #include <endian.h>
   33 
   34 #include <zlib.h>
   35 
   36 #include <caml/alloc.h>
   37 #include <caml/fail.h>
   38 #include <caml/memory.h>
   39 #include <caml/mlvalues.h>
   40 
   41 /* This vital function returns the offset of the virtual address
   42  * relative to the base address.  If the virtual address is outside
   43  * the kernel, then it returns -1.
   44  *
   45  * Note that the function is declared "noalloc" for speed.  It must
   46  * not allocate anything on the OCaml heap.
   47  *
   48  * str_mapping : int64 -> int64 -> int -> int
   49  */
   50 value
   51 virt_dmesg_str_mapping (value base_addrv, value addrv, value str_lenv)
   52 {
   53   uint64_t base_addr = Int64_val (base_addrv);
   54   uint64_t addr = Int64_val (addrv);
   55   int str_len = Int_val (str_lenv);
   56   uint64_t off;
   57 
   58   off = addr - base_addr;
   59   if (off < str_len)
   60     return Val_int (off);
   61   else
   62     return Val_int (-1);
   63 }
   64 
   65 /* NOTE: Declared as a "noalloc" function for speed. */
   66 value
   67 virt_dmesg_addr_compare (value a1v, value a2v)
   68 {
   69   uint64_t a1 = Int64_val (a1v);
   70   uint64_t a2 = Int64_val (a2v);
   71 
   72   if (a1 < a2)
   73     return (Val_int (-1));
   74   else if (a1 > a2)
   75     return (Val_int (1));
   76   else
   77     return (Val_int (0));
   78 }
   79 
   80 /* Find 'needle' in 'haystack', but start searching haystack from 'off'.
   81  *
   82  * strstr_from : string -> string -> int -> int
   83  */
   84 value
   85 virt_dmesg_strstr_from (value haystackv, value needlev, value offv)
   86 {
   87   CAMLparam3 (haystackv, needlev, offv);
   88   const char *haystack = String_val (haystackv);
   89   int off = Int_val (offv);
   90   const char *r;
   91   ptrdiff_t i;
   92 
   93   /* Because OCaml strings can contain '\0' characters, use memmem
   94    * not strstr.
   95    */
   96   r = memmem (haystack + off, caml_string_length (haystackv) - off,
   97               String_val (needlev), caml_string_length (needlev));
   98   if (r == 0)
   99     caml_raise_not_found ();
  100 
  101   i = r - haystack;
  102   CAMLreturn (Val_int (i));
  103 }
  104 
  105 /* This is like 'strstr_from' but it only tests for aligned 'needle',
  106  * eg. if 'needle' was 4 bytes long then it would only look every 4
  107  * bytes.
  108  */
  109 value
  110 virt_dmesg_strstr_from_aligned (value haystackv, value needlev, value offv)
  111 {
  112   CAMLparam3 (haystackv, needlev, offv);
  113   const char *haystack = String_val (haystackv);
  114   size_t haystack_len = caml_string_length (haystackv);
  115   const char *needle = String_val (needlev);
  116   size_t needle_len = caml_string_length (needlev);
  117   int off = Int_val (offv);
  118   int r;
  119 
  120   for (r = off; r < haystack_len; r += needle_len) {
  121     if (memcmp (haystack + r, needle, needle_len) == 0)
  122       goto found;
  123   }
  124   caml_raise_not_found ();
  125 
  126  found:
  127   CAMLreturn (Val_int (r));
  128 }
  129 
  130 /* Extract endian 32 and 64 bit integers (or pointers) from strings. */
  131 value
  132 virt_dmesg_str_get_le32 (value strv, value offv)
  133 {
  134   CAMLparam2 (strv, offv);
  135   CAMLlocal1 (rv);
  136   const char *str = String_val (strv);
  137   int off = Int_val (offv);
  138   uint64_t r;
  139 
  140   r = le32toh (*(const uint32_t *)(str + off));
  141   rv = caml_copy_int64 (r);
  142 
  143   CAMLreturn (rv);
  144 }
  145 
  146 value
  147 virt_dmesg_str_get_be32 (value strv, value offv)
  148 {
  149   CAMLparam2 (strv, offv);
  150   CAMLlocal1 (rv);
  151   const char *str = String_val (strv);
  152   int off = Int_val (offv);
  153   uint64_t r;
  154 
  155   r = be32toh (*(const uint32_t *)(str + off));
  156   rv = caml_copy_int64 (r);
  157 
  158   CAMLreturn (rv);
  159 }
  160 
  161 value
  162 virt_dmesg_str_get_le64 (value strv, value offv)
  163 {
  164   CAMLparam2 (strv, offv);
  165   CAMLlocal1 (rv);
  166   const char *str = String_val (strv);
  167   int off = Int_val (offv);
  168   uint64_t r;
  169 
  170   r = le64toh (*(const uint64_t *)(str + off));
  171   rv = caml_copy_int64 (r);
  172 
  173   CAMLreturn (rv);
  174 }
  175 
  176 value
  177 virt_dmesg_str_get_be64 (value strv, value offv)
  178 {
  179   CAMLparam2 (strv, offv);
  180   CAMLlocal1 (rv);
  181   const char *str = String_val (strv);
  182   int off = Int_val (offv);
  183   uint64_t r;
  184 
  185   r = be64toh (*(const uint64_t *)(str + off));
  186   rv = caml_copy_int64 (r);
  187 
  188   CAMLreturn (rv);
  189 }
  190 
  191 /* Convert integers of various endianness/word size to strings of bytes.
  192  *
  193  * str_of_*32 returns a 4 byte string
  194  * str_of_*64 returns an 8 byte string
  195  */
  196 value
  197 virt_dmesg_str_of_le32 (value addrv)
  198 {
  199   CAMLparam1 (addrv);
  200   CAMLlocal1 (rv);
  201   const char *str;
  202 
  203   rv = caml_alloc_string (4);
  204   str = String_val (rv);
  205   *(uint32_t *)str = htole32 (Int64_val (addrv));
  206 
  207   CAMLreturn (rv);
  208 }
  209 
  210 value
  211 virt_dmesg_str_of_be32 (value addrv)
  212 {
  213   CAMLparam1 (addrv);
  214   CAMLlocal1 (rv);
  215   const char *str;
  216 
  217   rv = caml_alloc_string (4);
  218   str = String_val (rv);
  219   *(uint32_t *)str = htobe32 (Int64_val (addrv));
  220 
  221   CAMLreturn (rv);
  222 }
  223 
  224 value
  225 virt_dmesg_str_of_le64 (value addrv)
  226 {
  227   CAMLparam1 (addrv);
  228   CAMLlocal1 (rv);
  229   const char *str;
  230 
  231   rv = caml_alloc_string (8);
  232   str = String_val (rv);
  233   *(uint64_t *)str = htole64 (Int64_val (addrv));
  234 
  235   CAMLreturn (rv);
  236 }
  237 
  238 value
  239 virt_dmesg_str_of_be64 (value addrv)
  240 {
  241   CAMLparam1 (addrv);
  242   CAMLlocal1 (rv);
  243   const char *str;
  244 
  245   rv = caml_alloc_string (8);
  246   str = String_val (rv);
  247   *(uint64_t *)str = htobe64 (Int64_val (addrv));
  248 
  249   CAMLreturn (rv);
  250 }
  251 
  252 /* Get NUL-terminated (ASCIIZ) string at the given offset.
  253  *
  254  * get_asciiz : string -> int -> string
  255  */
  256 value
  257 virt_dmesg_get_asciiz (value strv, value offv)
  258 {
  259   CAMLparam2 (strv, offv);
  260   CAMLlocal1 (rv);
  261   const char *str = String_val (strv);
  262   size_t len = caml_string_length (strv);
  263   int off = Int_val (offv);
  264   size_t rlen;
  265 
  266   /* Work out the length of the return value. */
  267   for (rlen = 0; off+rlen < len; ++rlen)
  268     if (str[off+rlen] == '\0')
  269       break;
  270 
  271   rv = caml_alloc_string (rlen);
  272   /* Previous allocation could have moved the input string, so ...  */
  273   str = String_val (strv);
  274 
  275   memcpy (String_val (rv), &str[off], rlen);
  276 
  277   CAMLreturn (rv);
  278 }
  279 
  280 /* Return true iff what is at the offset is plausibly a C programming
  281  * language identifier.
  282  *
  283  * is_C_ident : string -> int -> bool
  284  */
  285 value
  286 virt_dmesg_is_C_ident (value strv, value offv)
  287 {
  288   CAMLparam2 (strv, offv);
  289   const char *str = String_val (strv);
  290   size_t len = caml_string_length (strv);
  291   int off = Int_val (offv);
  292   size_t i;
  293   int r = 1 /* true */;
  294 
  295   if (str[off] != '_' && !(str[off] >= 'A' && str[off] <= 'Z' ||
  296                            str[off] >= 'a' && str[off] <= 'z')) {
  297     r = 0 /* false */;
  298     goto out;
  299   }
  300 
  301   for (i = 1; off+i < len; ++i) {
  302     if (str[off+i] == '\0')
  303       break;
  304 
  305     if (str[off+i] != '_' && !(str[off+i] >= 'A' && str[off+i] <= 'Z' ||
  306                                str[off+i] >= 'a' && str[off+i] <= 'z' ||
  307                                str[off+i] >= '0' && str[off+i] <= '9')) {
  308       r = 0 /* false */;
  309       goto out;
  310     }
  311   }
  312 
  313  out:
  314   CAMLreturn (Val_int (r));
  315 }
  316 
  317 /* external crc32_of_string : string -> int32 */
  318 value
  319 virt_dmesg_crc32_of_string (value strv)
  320 {
  321   CAMLparam1 (strv);
  322   CAMLlocal1 (rv);
  323   uLong r;
  324 
  325   r = crc32 (0, Z_NULL, 0);
  326   r = crc32 (r, String_val (strv), caml_string_length (strv));
  327 
  328   rv = caml_copy_int32 (r);
  329   CAMLreturn (rv);
  330 }