getdata.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. getdata.c - implementation of the elf_getdata(3) function.
  3. Copyright (C) 1995 - 2001 Michael Riepe
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library 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 GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  15. */
  16. #include <private.h>
  17. #ifndef lint
  18. static const char rcsid[] = "@(#) $Id: getdata.c,v 1.13 2008/05/23 08:15:34 michael Exp $";
  19. #endif /* lint */
  20. static Elf_Data*
  21. _elf_cook_scn(Elf *elf, Elf_Scn *scn, Scn_Data *sd) {
  22. Elf_Data dst;
  23. Elf_Data src;
  24. int flag = 0;
  25. size_t dlen;
  26. elf_assert(elf->e_data);
  27. /*
  28. * Prepare source
  29. */
  30. src = sd->sd_data;
  31. src.d_version = elf->e_version;
  32. if (elf->e_rawdata) {
  33. src.d_buf = elf->e_rawdata + scn->s_offset;
  34. }
  35. else {
  36. src.d_buf = elf->e_data + scn->s_offset;
  37. }
  38. /*
  39. * Prepare destination (needs prepared source!)
  40. */
  41. dst = sd->sd_data;
  42. if (elf->e_class == ELFCLASS32) {
  43. dlen = _elf32_xltsize(&src, dst.d_version, elf->e_encoding, 0);
  44. }
  45. #if __LIBELF64
  46. else if (elf->e_class == ELFCLASS64) {
  47. dlen = _elf64_xltsize(&src, dst.d_version, elf->e_encoding, 0);
  48. }
  49. #endif /* __LIBELF64 */
  50. else {
  51. elf_assert(valid_class(elf->e_class));
  52. seterr(ERROR_UNIMPLEMENTED);
  53. return NULL;
  54. }
  55. if (dlen == (size_t)-1) {
  56. return NULL;
  57. }
  58. dst.d_size = dlen;
  59. if (elf->e_rawdata != elf->e_data && dst.d_size <= src.d_size) {
  60. dst.d_buf = elf->e_data + scn->s_offset;
  61. }
  62. else if (!(dst.d_buf = malloc(dst.d_size))) {
  63. seterr(ERROR_MEM_SCNDATA);
  64. return NULL;
  65. }
  66. else {
  67. flag = 1;
  68. }
  69. /*
  70. * Translate data
  71. */
  72. if (_elf_xlatetom(elf, &dst, &src)) {
  73. sd->sd_memdata = (char*)dst.d_buf;
  74. sd->sd_data = dst;
  75. if (!(sd->sd_free_data = flag)) {
  76. elf->e_cooked = 1;
  77. }
  78. return &sd->sd_data;
  79. }
  80. if (flag) {
  81. free(dst.d_buf);
  82. }
  83. return NULL;
  84. }
  85. Elf_Data*
  86. elf_getdata(Elf_Scn *scn, Elf_Data *data) {
  87. Scn_Data *sd;
  88. Elf *elf;
  89. if (!scn) {
  90. return NULL;
  91. }
  92. elf_assert(scn->s_magic == SCN_MAGIC);
  93. if (scn->s_index == SHN_UNDEF) {
  94. seterr(ERROR_NULLSCN);
  95. }
  96. else if (data) {
  97. for (sd = scn->s_data_1; sd; sd = sd->sd_link) {
  98. elf_assert(sd->sd_magic == DATA_MAGIC);
  99. elf_assert(sd->sd_scn == scn);
  100. if (data == &sd->sd_data) {
  101. /*
  102. * sd_link allocated by elf_newdata().
  103. */
  104. return &sd->sd_link->sd_data;
  105. }
  106. }
  107. seterr(ERROR_SCNDATAMISMATCH);
  108. }
  109. else if ((sd = scn->s_data_1)) {
  110. elf_assert(sd->sd_magic == DATA_MAGIC);
  111. elf_assert(sd->sd_scn == scn);
  112. elf = scn->s_elf;
  113. elf_assert(elf);
  114. elf_assert(elf->e_magic == ELF_MAGIC);
  115. if (sd->sd_freeme) {
  116. /* allocated by elf_newdata() */
  117. return &sd->sd_data;
  118. }
  119. else if (scn->s_type == SHT_NULL) {
  120. seterr(ERROR_NULLSCN);
  121. }
  122. else if (sd->sd_memdata) {
  123. /* already cooked */
  124. return &sd->sd_data;
  125. }
  126. else if (scn->s_offset < 0 || scn->s_offset > elf->e_size) {
  127. seterr(ERROR_OUTSIDE);
  128. }
  129. else if (scn->s_type == SHT_NOBITS || !scn->s_size) {
  130. /* no data to read */
  131. return &sd->sd_data;
  132. }
  133. else if (scn->s_offset + scn->s_size > elf->e_size) {
  134. seterr(ERROR_TRUNC_SCN);
  135. }
  136. else if (valid_class(elf->e_class)) {
  137. return _elf_cook_scn(elf, scn, sd);
  138. }
  139. else {
  140. seterr(ERROR_UNKNOWN_CLASS);
  141. }
  142. }
  143. return NULL;
  144. }