newscn.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * newscn.c - implementation of the elf_newscn(3) function.
  3. * Copyright (C) 1995 - 2006 Michael Riepe
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Library General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Library General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Library General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. */
  19. #include <private.h>
  20. #ifndef lint
  21. static const char rcsid[] = "@(#) $Id: newscn.c,v 1.13 2008/05/23 08:15:35 michael Exp $";
  22. #endif /* lint */
  23. int
  24. _elf_update_shnum(Elf *elf, size_t shnum) {
  25. size_t extshnum = 0;
  26. Elf_Scn *scn;
  27. elf_assert(elf);
  28. elf_assert(elf->e_ehdr);
  29. scn = elf->e_scn_1;
  30. elf_assert(scn);
  31. elf_assert(scn->s_index == 0);
  32. if (shnum >= SHN_LORESERVE) {
  33. extshnum = shnum;
  34. shnum = 0;
  35. }
  36. if (elf->e_class == ELFCLASS32) {
  37. ((Elf32_Ehdr*)elf->e_ehdr)->e_shnum = shnum;
  38. scn->s_shdr32.sh_size = extshnum;
  39. }
  40. #if __LIBELF64
  41. else if (elf->e_class == ELFCLASS64) {
  42. ((Elf64_Ehdr*)elf->e_ehdr)->e_shnum = shnum;
  43. scn->s_shdr64.sh_size = extshnum;
  44. }
  45. #endif /* __LIBELF64 */
  46. else {
  47. if (valid_class(elf->e_class)) {
  48. seterr(ERROR_UNIMPLEMENTED);
  49. }
  50. else {
  51. seterr(ERROR_UNKNOWN_CLASS);
  52. }
  53. return -1;
  54. }
  55. elf->e_ehdr_flags |= ELF_F_DIRTY;
  56. scn->s_shdr_flags |= ELF_F_DIRTY;
  57. return 0;
  58. }
  59. static Elf_Scn*
  60. _makescn(Elf *elf, size_t index) {
  61. Elf_Scn *scn;
  62. elf_assert(elf);
  63. elf_assert(elf->e_magic == ELF_MAGIC);
  64. elf_assert(elf->e_ehdr);
  65. elf_assert(_elf_scn_init.s_magic == SCN_MAGIC);
  66. if (!(scn = (Elf_Scn*)malloc(sizeof(*scn)))) {
  67. seterr(ERROR_MEM_SCN);
  68. return NULL;
  69. }
  70. *scn = _elf_scn_init;
  71. scn->s_elf = elf;
  72. scn->s_scn_flags = ELF_F_DIRTY;
  73. scn->s_shdr_flags = ELF_F_DIRTY;
  74. scn->s_freeme = 1;
  75. scn->s_index = index;
  76. return scn;
  77. }
  78. Elf_Scn*
  79. _elf_first_scn(Elf *elf) {
  80. Elf_Scn *scn;
  81. elf_assert(elf);
  82. elf_assert(elf->e_magic == ELF_MAGIC);
  83. if ((scn = elf->e_scn_1)) {
  84. return scn;
  85. }
  86. if ((scn = _makescn(elf, 0))) {
  87. elf->e_scn_1 = elf->e_scn_n = scn;
  88. if (_elf_update_shnum(elf, 1)) {
  89. free(scn);
  90. elf->e_scn_1 = elf->e_scn_n = scn = NULL;
  91. }
  92. }
  93. return scn;
  94. }
  95. static Elf_Scn*
  96. _buildscn(Elf *elf) {
  97. Elf_Scn *scn;
  98. if (!_elf_first_scn(elf)) {
  99. return NULL;
  100. }
  101. scn = elf->e_scn_n;
  102. elf_assert(scn);
  103. if (!(scn = _makescn(elf, scn->s_index + 1))) {
  104. return NULL;
  105. }
  106. if (_elf_update_shnum(elf, scn->s_index + 1)) {
  107. free(scn);
  108. return NULL;
  109. }
  110. elf->e_scn_n = elf->e_scn_n->s_link = scn;
  111. return scn;
  112. }
  113. Elf_Scn*
  114. elf_newscn(Elf *elf) {
  115. Elf_Scn *scn;
  116. if (!elf) {
  117. return NULL;
  118. }
  119. elf_assert(elf->e_magic == ELF_MAGIC);
  120. if (!elf->e_readable && !elf->e_ehdr) {
  121. seterr(ERROR_NOEHDR);
  122. }
  123. else if (elf->e_kind != ELF_K_ELF) {
  124. seterr(ERROR_NOTELF);
  125. }
  126. else if (!elf->e_ehdr && !_elf_cook(elf)) {
  127. return NULL;
  128. }
  129. else if ((scn = _buildscn(elf))) {
  130. return scn;
  131. }
  132. return NULL;
  133. }