ldbuildid.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* ldbuildid.c - Build Id support routines
  2. Copyright (C) 2013-2022 Free Software Foundation, Inc.
  3. This file is part of the GNU Binutils.
  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 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #include "safe-ctype.h"
  19. #include "md5.h"
  20. #include "sha1.h"
  21. #include "ldbuildid.h"
  22. #ifdef __MINGW32__
  23. #include <windows.h>
  24. #include <rpcdce.h>
  25. #endif
  26. #define streq(a,b) strcmp ((a), (b)) == 0
  27. bool
  28. validate_build_id_style (const char *style)
  29. {
  30. if ((streq (style, "md5")) || (streq (style, "sha1"))
  31. || (streq (style, "uuid")) || (startswith (style, "0x")))
  32. return true;
  33. return false;
  34. }
  35. bfd_size_type
  36. compute_build_id_size (const char *style)
  37. {
  38. if (streq (style, "md5") || streq (style, "uuid"))
  39. return 128 / 8;
  40. if (streq (style, "sha1"))
  41. return 160 / 8;
  42. if (startswith (style, "0x"))
  43. {
  44. bfd_size_type size = 0;
  45. /* ID is in string form (hex). Count the bytes. */
  46. const char *id = style + 2;
  47. do
  48. {
  49. if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
  50. {
  51. ++size;
  52. id += 2;
  53. }
  54. else if (*id == '-' || *id == ':')
  55. ++id;
  56. else
  57. {
  58. size = 0;
  59. break;
  60. }
  61. } while (*id != '\0');
  62. return size;
  63. }
  64. return 0;
  65. }
  66. static unsigned char
  67. read_hex (const char xdigit)
  68. {
  69. if (ISDIGIT (xdigit))
  70. return xdigit - '0';
  71. if (ISUPPER (xdigit))
  72. return xdigit - 'A' + 0xa;
  73. if (ISLOWER (xdigit))
  74. return xdigit - 'a' + 0xa;
  75. abort ();
  76. return 0;
  77. }
  78. bool
  79. generate_build_id (bfd *abfd,
  80. const char *style,
  81. checksum_fn checksum_contents,
  82. unsigned char *id_bits,
  83. int size ATTRIBUTE_UNUSED)
  84. {
  85. if (streq (style, "md5"))
  86. {
  87. struct md5_ctx ctx;
  88. md5_init_ctx (&ctx);
  89. if (!(*checksum_contents) (abfd, (sum_fn) &md5_process_bytes, &ctx))
  90. return false;
  91. md5_finish_ctx (&ctx, id_bits);
  92. }
  93. else if (streq (style, "sha1"))
  94. {
  95. struct sha1_ctx ctx;
  96. sha1_init_ctx (&ctx);
  97. if (!(*checksum_contents) (abfd, (sum_fn) &sha1_process_bytes, &ctx))
  98. return false;
  99. sha1_finish_ctx (&ctx, id_bits);
  100. }
  101. else if (streq (style, "uuid"))
  102. {
  103. #ifndef __MINGW32__
  104. int n;
  105. int fd = open ("/dev/urandom", O_RDONLY);
  106. if (fd < 0)
  107. return false;
  108. n = read (fd, id_bits, size);
  109. close (fd);
  110. if (n < size)
  111. return false;
  112. #else /* __MINGW32__ */
  113. typedef RPC_STATUS (RPC_ENTRY * UuidCreateFn) (UUID *);
  114. UUID uuid;
  115. UuidCreateFn uuid_create = 0;
  116. HMODULE rpc_library = LoadLibrary ("rpcrt4.dll");
  117. if (!rpc_library)
  118. return false;
  119. uuid_create = (UuidCreateFn) (void (WINAPI *)(void)) GetProcAddress (rpc_library, "UuidCreate");
  120. if (!uuid_create)
  121. {
  122. FreeLibrary (rpc_library);
  123. return false;
  124. }
  125. if (uuid_create (&uuid) != RPC_S_OK)
  126. {
  127. FreeLibrary (rpc_library);
  128. return false;
  129. }
  130. FreeLibrary (rpc_library);
  131. memcpy (id_bits, &uuid,
  132. (size_t) size < sizeof (UUID) ? (size_t) size : sizeof (UUID));
  133. #endif /* __MINGW32__ */
  134. }
  135. else if (startswith (style, "0x"))
  136. {
  137. /* ID is in string form (hex). Convert to bits. */
  138. const char *id = style + 2;
  139. size_t n = 0;
  140. do
  141. {
  142. if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
  143. {
  144. id_bits[n] = read_hex (*id++) << 4;
  145. id_bits[n++] |= read_hex (*id++);
  146. }
  147. else if (*id == '-' || *id == ':')
  148. ++id;
  149. else
  150. abort (); /* Should have been validated earlier. */
  151. }
  152. while (*id != '\0');
  153. }
  154. else
  155. abort (); /* Should have been validated earlier. */
  156. return true;
  157. }