| 186 | } |
| 187 | |
| 188 | Error Assembler::bind(const Label& label) { |
| 189 | if (_lastError) return _lastError; |
| 190 | ASMJIT_ASSERT(_code != nullptr); |
| 191 | |
| 192 | LabelEntry* le = _code->getLabelEntry(label); |
| 193 | if (ASMJIT_UNLIKELY(!le)) |
| 194 | return setLastError(DebugUtils::errored(kErrorInvalidLabel)); |
| 195 | |
| 196 | // Label can be bound only once. |
| 197 | if (ASMJIT_UNLIKELY(le->isBound())) |
| 198 | return setLastError(DebugUtils::errored(kErrorLabelAlreadyBound)); |
| 199 | |
| 200 | #if !defined(ASMJIT_DISABLE_LOGGING) |
| 201 | if (_globalOptions & kOptionLoggingEnabled) { |
| 202 | StringBuilderTmp<256> sb; |
| 203 | if (le->hasName()) |
| 204 | sb.setFormat("%s:", le->getName()); |
| 205 | else |
| 206 | sb.setFormat("L%u:", Operand::unpackId(label.getId())); |
| 207 | |
| 208 | size_t binSize = 0; |
| 209 | if (!_code->_logger->hasOption(Logger::kOptionBinaryForm)) |
| 210 | binSize = Globals::kInvalidIndex; |
| 211 | |
| 212 | Logging::formatLine(sb, nullptr, binSize, 0, 0, getInlineComment()); |
| 213 | _code->_logger->log(sb.getData(), sb.getLength()); |
| 214 | } |
| 215 | #endif // !ASMJIT_DISABLE_LOGGING |
| 216 | |
| 217 | Error err = kErrorOk; |
| 218 | size_t pos = getOffset(); |
| 219 | |
| 220 | LabelLink* link = le->_links; |
| 221 | LabelLink* prev = nullptr; |
| 222 | |
| 223 | while (link) { |
| 224 | intptr_t offset = link->offset; |
| 225 | uint32_t relocId = link->relocId; |
| 226 | |
| 227 | if (relocId != RelocEntry::kInvalidId) { |
| 228 | // Adjust relocation data. |
| 229 | RelocEntry* re = _code->_relocations[relocId]; |
| 230 | re->_data += static_cast<uint64_t>(pos); |
| 231 | } |
| 232 | else { |
| 233 | // Not using relocId, this means that we are overwriting a real |
| 234 | // displacement in the CodeBuffer. |
| 235 | int32_t patchedValue = static_cast<int32_t>( |
| 236 | static_cast<intptr_t>(pos) - offset + link->rel); |
| 237 | |
| 238 | // Size of the value we are going to patch. Only BYTE/DWORD is allowed. |
| 239 | uint32_t size = _bufferData[offset]; |
| 240 | if (size == 4) |
| 241 | Utils::writeI32u(_bufferData + offset, static_cast<int32_t>(patchedValue)); |
| 242 | else if (size == 1 && Utils::isInt8(patchedValue)) |
| 243 | _bufferData[offset] = static_cast<uint8_t>(patchedValue & 0xFF); |
| 244 | else |
| 245 | err = DebugUtils::errored(kErrorInvalidDisplacement); |
no test coverage detected