10a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu/*
20a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * Copyright 2011, The Android Open Source Project
30a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu *
40a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * Licensed under the Apache License, Version 2.0 (the "License");
50a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * you may not use this file except in compliance with the License.
60a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * You may obtain a copy of the License at
70a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu *
80a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu *     http://www.apache.org/licenses/LICENSE-2.0
90a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu *
100a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * Unless required by applicable law or agreed to in writing, software
110a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * distributed under the License is distributed on an "AS IS" BASIS,
120a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * See the License for the specific language governing permissions and
140a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu * limitations under the License.
150a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu */
160a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
170a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu#include <stdio.h>
180a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu#include "GOT.h"
190a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
200a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fuvoid *got_symbol_addresses[NUM_OF_GOT_ENTRY];
210a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fuint got_symbol_indexes[NUM_OF_GOT_ENTRY];
220a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fusize_t got_symbol_count = 0;
230a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
240a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fuvoid *got_address()
250a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu{
260a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  return &got_symbol_addresses[0];
270a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu}
280a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
290a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fuint search_got(int symbol_index, void *addr, uint8_t bind_type)
300a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu{
310a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  size_t i;
320a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
330a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  // For local symbols (R_MIPS_GOT16), we only store the high 16-bit value
340a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  // after adding 0x8000.
350a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  if (bind_type == STB_LOCAL)
368d2a1230eae323981b4f6e03406e801a51018432Logan Chien    addr = (void *)(((intptr_t)addr + 0x8000) & 0xFFFF0000);
370a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
380a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  for (i = 0; i < got_symbol_count; i++) {
390a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    if (got_symbol_indexes[i] == symbol_index) {
400a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      if (bind_type == STB_LOCAL) {
410a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        // Check if the value is the same for local symbols.
420a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        // If yes, we can reuse this entry.
430a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        // If not, we continue searching.
440a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        if (got_symbol_addresses[i] == addr) {
450a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          return i;
460a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        }
470a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
480a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      else {
490a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        // The value must be the same for global symbols .
500a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        rsl_assert (got_symbol_addresses[i] == addr
510a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu                    && "MIPS GOT address error.");
520a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        return i;
530a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
540a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    }
550a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  }
560a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
570a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  // Cannot find this symbol with correct value, so we need to create one
580a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  rsl_assert (got_symbol_count < NUM_OF_GOT_ENTRY && "MIPS GOT is full.");
590a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  got_symbol_indexes[got_symbol_count] = symbol_index;
600a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  got_symbol_addresses[got_symbol_count] = addr;
610a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  got_symbol_count++;
620a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu  return (got_symbol_count - 1);
630a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu}
64